Merged changes from default

--HG--
branch : 8u40-verified-fixes
diff --git a/.hgtags b/.hgtags
index 496dc04..a13b682 100644
--- a/.hgtags
+++ b/.hgtags
@@ -322,6 +322,8 @@
 4b9cc65dd24d398c4f921c0beccfb8caeaaaf584 jdk8u25-b17
 cdbf34dbef404b47805c8c85b11c65c2afaa6674 jdk8u25-b18
 4f9e65387c21831d0ea5726641a302c2ce73a4cc jdk8u25-b31
+be20e9a00818df15af12544c21839c3a3d5768d9 jdk8u25-b32
+a8526abf70a8c98aee5fed64eb727210745a6e5a jdk8u25-b33
 9b692a6e5f22228f822973d35610d37cb9dd9693 jdk8u31-b00
 6bf53bb6c969678488b1c073d56dd55df1a0ea17 jdk8u31-b01
 809bf97d7e70dcb3873fcbc10f12f62580b1c11d jdk8u31-b02
@@ -336,6 +338,10 @@
 599bd596fa549d882aa8fc5104c322a75a3af728 jdk8u31-b11
 f36c71a03e4ed467f630cc46d076a5bb4c58b6d5 jdk8u31-b12
 ec36fa3b35eb00f053d624ae837579c6b8e446ac jdk8u31-b13
+34a64e22b81bd78cf29603a80ff1f4cfc1694df8 jdk8u31-b31
+d2b5784a3452a4fd9d1ccfefe93ee2d36662842c jdk8u31-b32
+c6dd08613a440ed8d0f1b14b85911d6f3826e1d4 jdk8u31-b33
+e92af20b58190a0fa46c2c93636368866e274b39 jdk8u31-b34
 f2925491b61b22ac42f8c30ee9c6723ffa401a4c jdk8u40-b00
 62468d841b842769d875bd97d10370585c296eb7 jdk8u40-b01
 b476c69c820ac1e05071f4de5abab8e2dff80e87 jdk8u40-b02
@@ -364,3 +370,150 @@
 fb7b6c2b95c5661f15e8e747a63ec6d95d49fe46 jdk8u40-b25
 b142a2d8e35e54abb08a7ded1dbfb5d7ce534c93 jdk8u40-b26
 c2dd88e89edc85b1bcb731d3296d0fcec1b78447 jdk8u40-b27
+e05552220ba82e465a1abfee90224b5b247e37bc jdk8u40-b31
+e1cc0fe0fd50fc4582e729897d7095ffce0f97ad jdk8u40-b32
+05a3614ed5276e5db2a73cce918be04b1a2922fb jdk8u45-b00
+21ec16eb7e6346c78b4fa67ccd6d2a9c58f0b696 jdk8u45-b01
+37b3ef9a07323afd2556d6837824db154cccc874 jdk8u45-b02
+ed3a4177da50d75d6da55ff521bf3f971cfe5214 jdk8u45-b03
+65f24dedfd29ec02af43f745742647412d90f005 jdk8u45-b04
+de2ee4c1341fd4eeaba39b81194df0c4274e7c8b jdk8u45-b05
+cf0097b8987d2d2f480d8a6d2a8f235509bd4421 jdk8u45-b06
+bb112473c7314146bebb75fb5220b4ec641b0b7a jdk8u45-b07
+8ab14ee47c8b1558854d3cd71006eceb6c6804d1 jdk8u45-b08
+397ea4a1bff8adbceaa1a40ff826b3d2d3b09e81 jdk8u45-b09
+c650c13d2bdf0e869ae86685de6bbb8a4e983ca3 jdk8u45-b10
+6ae873ddbe195aa966fc348e468c0ecd2702f5e3 jdk8u45-b11
+9b9fee0f99cd07fba62abaafe705665a5ab89067 jdk8u45-b12
+6fda38586f73de706ecde311711a587ac49d51d8 jdk8u45-b13
+d5477c6d1678547a9338707adc4b81d35c280454 jdk8u45-b14
+ea15c34524408bbd2fa2886e5ec5d7995d8e236a jdk8u45-b15
+d1c1e084430027bffb5bbb1b288660fbdb86627b jdk8u45-b31
+67dc09b4965989a65a97e0bfec73338cd4763f2a jdk8u45-b32
+104fe9b448e045b5a07dbf5246350077d5b5c23a jdk8u45-b33
+9595ce9f639a52bf288c3d55615b5ab295f37d7d jdk8u45-b34
+c5847f4fd548048e4cb819f1a93e03527a1eb136 jdk8u45-b35
+665716d2b552d5cb8b8fe32c4f5723c50cb17cf9 jdk8u45-b36
+e383d55965d89f5cdaba0cef8ac6372aae9fe56b jdk8u45-b37
+2d1c01990ebd896f81f511aabf1e53cbe1fda11f jdk8u51-b00
+4323de82a85c378b08e24601b8f3cec6aafda6f4 jdk8u51-b01
+5ee412753fa08a1e9fa15221c4253886e822a94e jdk8u51-b02
+a6d6f7cf488c1e57df9e9f724547c0e0eae2ad9e jdk8u51-b03
+7512eafda1f90fbf6837dd29ae7585b19b9fbe3a jdk8u51-b04
+04aae4de5c5e2b1c51725a7181afa0085a78d7ee jdk8u51-b05
+a03caffca13caafe4e0a14b5c6cee333bdfce67c jdk8u51-b06
+8814ac4bd7bc1cf87b40f036dc306185343ddb76 jdk8u51-b07
+7fa927b4a47ab76204ec2befe3b8f52336c0a291 jdk8u51-b08
+77cee35f987167f6e97cc8f2b09349e743e7a9e7 jdk8u51-b09
+1480e27e4af65e809c1a5cc0310616c2c68392f2 jdk8u51-b10
+6e95b9bb2f67d4a77d28e5aa3c07281fc8424823 jdk8u51-b11
+bf2fe867628bf323262377f8312c85f440a9b246 jdk8u51-b12
+1ecbb6d582a6ccf9e0f6e359a925155c8c580bac jdk8u51-b13
+e9d85a30fd08425904a400add72212a010381aa8 jdk8u51-b14
+4cbc78843829b3f6de43b3c056565834008419a6 jdk8u51-b15
+f01ca5e6b907d1fc2c17068fb28a74411e833f16 jdk8u51-b16
+4e5f9de7a3dfd0c4e15714863007ac591e9dffea jdk8u51-b31
+009644f58d73263eec2582a84a1e9b63975c5387 jdk8u51-b32
+eac4b87f86dde817023a07dcb701dc5d986b705f jdk8u51-b33
+6ec61d2494283fbaca6df227f1a5b45487dc1ca7 jdk8u60-b00
+af290f203369ecf8e67b89c4a3a8df0bf535230e jdk8u60-b01
+39e0c14d45c3fee93a29993f1415b3393d03483f jdk8u60-b02
+323f54e277dfcea814a32fa4b6b36876db18181f jdk8u60-b03
+b0b90d6c5265f45cee7fde968e15f8f272b5b24b jdk8u60-b04
+6f44964fbab316de02d58436be846b5e92813426 jdk8u60-b05
+4b7613f08fd3a6e738bc048d280630756d3593cd jdk8u60-b06
+80966e5cc384fb8c67938c0e05e2b990116d3f4c jdk8u60-b07
+e024db176497a3655f7c9d1d86571df74707ba62 jdk8u60-b08
+1f73439a45bf9cdb73ece75b2c935980657b10d4 jdk8u60-b09
+7aaa64363e1a632ab113b459c46a8ce0c32e4738 jdk8u60-b10
+f6f2d944a863be7d22ca7eac904b6d967abb6b39 jdk8u60-b11
+d03eb34e4b84296f4ce98a78f6c75c07218a678d jdk8u60-b12
+3628ab9fdbc0c58b9d97bc3cd5f3f7680d9785ff jdk8u60-b13
+24e7c53c5716bb52a3f33614b47b72cc134823c9 jdk8u60-b14
+78fcf7f0eac8ffa474518b315bdf84a1dbd6e76d jdk8u60-b15
+bf44ade6c2c2e697ccbc1e57f3eac870908614e6 jdk8u60-b16
+ff7052ce0f6b655d726cd0f77e9a5f8313361889 jdk8u60-b17
+0b5c0f02a0b79ae0aa97520d65e5b520af8f1b2a jdk8u60-b18
+3780124b6dbb100c2c4af2759b8f0e12a8bf1c4c jdk8u60-b19
+46a3d8588ad227dc390d84dfc0f89b9291395a36 jdk8u60-b20
+7475a2bd3c012f7dfd0532a344eb7efca56ac6e6 jdk8u60-b21
+9ed906919b5d92067edcdd966a3f413fca0f70ab jdk8u60-b22
+23165e806566f01cdc56421ea82c7e74a6fd85d5 jdk8u60-b23
+68107693248469f7b4fdcc35c53e4206a0d55087 jdk8u60-b24
+371f3f83f773ec97491d994bbcce834f0a2cca74 jdk8u60-b25
+58791cd01bc9aa973d8845ce63403b90d357b5ac jdk8u60-b26
+72a33aed7dccf570f4e05ea1121522a88ac190b2 jdk8u60-b27
+fc0045a6aaeee45f5d2505a2f7a07ec6cd6f56bc jdk8u60-b31
+2d161c9248ca7bf5779cf33c45768e26c1161eb4 jdk8u60-b32
+afc8b472a5f3d54734be29aa9c4f617191fc9246 jdk8u52-b06
+8cd2d9bea168694db5f090b30ba5973e1656385b jdk8u52-b07
+afc8b472a5f3d54734be29aa9c4f617191fc9246 jdk8u65-b00
+c9f36bcde982f8713c2767d1c882da85b1b9fb44 jdk8u65-b01
+398c895674d0f27711a52d442c1d1b471101f44b jdk8u65-b02
+db15ac4eff75c9b2b6535789d73f7fc8f84be70e jdk8u65-b03
+121f4183eff871ae9d3311781d5fbaf0e7dbe6e4 jdk8u65-b04
+3198826d0a96fa74c9e464de2fa2a2a45a08b9be jdk8u65-b05
+0709198e5515f5caa965f0b0603e367db3ed1160 jdk8u65-b06
+7f88899c78f96be2c0550b4e5a0576a98f45a96e jdk8u65-b07
+ed247f904308f124558a332f86dc9ee70698accb jdk8u65-b08
+45e0dbcb50591fa7dcb787dae7a4ab32ff1c1c1a jdk8u65-b09
+be2856f5c3e4ced88259759201fbb3d5c0e4db94 jdk8u65-b10
+6a809be8e2057b290871707aeaadf79679afbf90 jdk8u65-b11
+b9bc29802d24cf3e82f0b435c82d567e27373aa6 jdk8u65-b12
+5ad3832ac8d01656ec28d03f81042f2672360219 jdk8u65-b13
+1448629ede5316a04b15f66667a8cfc4bd1b5009 jdk8u65-b14
+7077dc107e60e994b599b103e6611c77fc37c0ea jdk8u65-b15
+0353cddbbf4e911a54cb6a8546f7df395a349e8b jdk8u65-b16
+df0218bcade38354fd70ae980aaa33088b8016dd jdk8u65-b17
+9ed906919b5d92067edcdd966a3f413fca0f70ab jdk8u66-b00
+c0f0613d1b1119afc9446eb187a2a7b5f534f050 jdk8u66-b01
+16220ab541af04fe79d9143fb62854f7acf46eca jdk8u66-b02
+3cd98cdbca8be17acd1eb3aed902303188b7e5f8 jdk8u66-b07
+a1436c975c531200de5133990886c1bac851a29f jdk8u66-b08
+d9eb8e3f1388b43f0e9c5ba2fdd91bf69295360a jdk8u66-b09
+998d6b5b976ba8db410b9f8cccf1cc927280b542 jdk8u66-b10
+46022f24d619e56ff41a432a5211bd9560d3e237 jdk8u66-b11
+2bdd08a9cc8ca594723e412cc9479f4f7351959f jdk8u66-b12
+cd562acc692c5ea4d5e3ea5164757f1b7e00e274 jdk8u66-b13
+165ed6982da8dc7dc5562d5b4a8f07dba55c7448 jdk8u66-b14
+9a3b86240761e602469c41bd720c7791997253e6 jdk8u66-b15
+c0ce5c308f5e2c42ac0d2e7367355663312a3128 jdk8u66-b16
+3cc16ff2735c6818b68fdf161ddbcc89a5b4db1a jdk8u66-b17
+39bfb9eb75dcb2176a87ac3b025a665c41244e54 jdk8u66-b18
+3e08bc604b2166b251833e522892ffcfd22b4b88 jdk8u66-b31
+a7ac4116ee88aa86fec5ac66901302e11f578172 jdk8u71-b00
+b8987f466586180cb4dc387f5fa290bb4cf34983 jdk8u71-b01
+a8fd49cb76fafc704b746a98bd18647802674d2d jdk8u71-b02
+12745568f9fb73a452d85b2388fef29909dafc24 jdk8u71-b03
+92b196168ef13e159e311e864c08d70e2c23dec6 jdk8u71-b04
+c870d760ca23b0f2c21813946eeb36563eeea8d4 jdk8u71-b05
+f76ef9364e15663fe29cda34f7d95cbab224ff36 jdk8u71-b06
+c3c1c032ff27f5967edcd595eeca23a005c8a7fe jdk8u71-b07
+0eb2b5f656d5d738957259d5f3f7982dc5b2a864 jdk8u71-b08
+79a56b0e79aa18f18c930236157458d7893537db jdk8u71-b09
+dcb78b4ac30e7ace9db4c53450b54226cc753505 jdk8u71-b10
+8d7818ff955da951165530e2c76154145a9f6098 jdk8u71-b11
+65e3e76835672759adf73ba583139d6c0b36d661 jdk8u71-b12
+0b0d8d3929e8c5e1f10e702f23aaf992a08974f2 jdk8u71-b13
+f2ca988f4efd4b68a6b675da70cad2f217ba88b8 jdk8u71-b14
+c577bcadb46d49f0a86edb459803ad233b722cfa jdk8u71-b15
+667e020da337e453eac8ecb9285c9b34a47e25fd jdk8u72-b00
+a105e7b0eff93895b82e3d372a63df4311d79821 jdk8u72-b01
+f7c3d65076a0c0bf1bb4ea633b4ea0af9ffb12fe jdk8u72-b02
+c47a6341ae31e394f6748acbeebf68de3ae285ff jdk8u72-b03
+4592976d8655d9ec0ad364901ae07c79813c8cd4 jdk8u72-b04
+0c87ce7cc7d01462476bce07945dc1646b4f08d1 jdk8u72-b05
+a2591c7bcb92f5bb2bd53b46d5a2c97be367f7fe jdk8u72-b06
+619a1ac46fc46394f524f7aa587f6c70d3d7ab52 jdk8u72-b07
+bcc30e9810fe0b3f19556dcfce0cdd801dbfe463 jdk8u72-b08
+1f69895e259bb6cbb4a5b2aead1c7bb341a58ec2 jdk8u72-b09
+390714be5c40a14a43f136a6dc2d15f38251a2d1 jdk8u72-b10
+e7a962a13695d244f31721ca322968e70c41f623 jdk8u72-b11
+b779108a142b80d9d8503c7220ad3bb7cb0dda53 jdk8u72-b12
+81e48503b62fd8814135f642905fe38056aaf2a9 jdk8u72-b13
+e48d06eeff82bea512cea44fa14d59b88067ef83 jdk8u72-b14
+769b21d1b85cfb57c11c89bbc8f185f9e520df66 jdk8u72-b15
+9ff5c21813330147bf08389b3992534780c93247 jdk8u76-b00
+b7bbed8b05dd50c27050c7e10e20d25329dcd32b jdk8u76-b01
+4c1aa7b8c43c6fd38f9c13a6df2264378dd6a873 jdk8u76-b02
+07db58f99673790d5139e8497552ac331e0824f5 jdk8u76-b03
diff --git a/README b/README
index 242d607..9cc6c72 100644
--- a/README
+++ b/README
@@ -72,14 +72,11 @@
 - Running tests
 
 Nashorn tests are TestNG based. Running tests requires downloading the
-TestNG library and placing its jar file into the lib subdirectory:
+TestNG library and placing its jar file into the test/lib subdirectory. This is
+done automatically when executing the "ant externals" command to get external
+test suites (see below).
 
-    # download and install TestNG
-    wget http://testng.org/testng-x.y.z.zip
-    unzip testng-x.y.z.zip
-    cp testng-x.y.z/testng-x.y.z.jar test/lib/testng.jar
-    
-After that, you can run the tests using:
+Once TestNG is properly installed, you can run the tests using:
     cd make
     ant clean test
     
diff --git a/THIRD_PARTY_README b/THIRD_PARTY_README
index c34ce6b..2b20da2 100644
--- a/THIRD_PARTY_README
+++ b/THIRD_PARTY_README
@@ -1140,37 +1140,6 @@
 
 --------------------------------------------------------------------------------
 
-%% This notice is provided with respect to JSON, which may be included 
-with JRE 8 & JDK 8.
-
---- begin of LICENSE ---
-
-Copyright (c) 2002 JSON.org
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-The Software shall be used for Good, not Evil.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
---- end of LICENSE ---
-
--------------------------------------------------------------------------------
-
 %% This notice is provided with respect to Kerberos functionality, which 
 which may be included with JRE 8, JDK 8, and OpenJDK 8.
 
@@ -1250,7 +1219,7 @@
 
 -------------------------------------------------------------------------------
 
-%% This notice is provided with respect to libpng 1.5.4, which may be 
+%% This notice is provided with respect to libpng 1.6.16, which may be 
 included with JRE 8, JDK 8, and OpenJDK 8.
 
 --- begin of LICENSE ---
@@ -1266,8 +1235,8 @@
 
 This code is released under the libpng license.
 
-libpng versions 1.2.6, August 15, 2004, through 1.5.4, July 7, 2011, are
-Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are
+libpng versions 1.2.6, August 15, 2004, through 1.6.16, December 22, 2014, are
+Copyright (c) 2004, 2006-2014 Glenn Randers-Pehrson, and are
 distributed according to the same disclaimer and license as libpng-1.2.5
 with the following individual added to the list of Contributing Authors
 
@@ -1364,13 +1333,13 @@
 
 Glenn Randers-Pehrson
 glennrp at users.sourceforge.net
-July 7, 2011
+December 22, 2014
 
 --- end of LICENSE ---
 
 -------------------------------------------------------------------------------
 
-%% This notice is provided with respect to libungif 4.1.3, which may be 
+%% This notice is provided with respect to GIFLIB 5.1.1 & libungif 4.1.3, which may be 
 included with JRE 8, JDK 8, and OpenJDK 8.
 
 --- begin of LICENSE ---
@@ -1399,13 +1368,13 @@
 
 -------------------------------------------------------------------------------
 
-%% This notice is provided with respect to Little CMS 2.5, which may be 
+%% This notice is provided with respect to Little CMS 2.7, which may be 
 included with JRE 8, JDK 8, and OpenJDK 8.
 
 --- begin of LICENSE ---
 
 Little CMS
-Copyright (c) 1998-2011 Marti Maria Saguer
+Copyright (c) 1998-2015 Marti Maria Saguer
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java
index 7587431..df740ef 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java
@@ -54,10 +54,9 @@
 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.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;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_TYPE;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_CREATEBUILTIN;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_CREATEBUILTIN_DESC;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_CREATEBUILTIN_SPECS_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_TYPE;
@@ -282,9 +281,9 @@
         assert specs != null;
         if (!specs.isEmpty()) {
             mi.memberInfoArray(className, specs);
-            mi.invokeStatic(SCRIPTFUNCTIONIMPL_TYPE, SCRIPTFUNCTIONIMPL_MAKEFUNCTION, SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC);
+            mi.invokeStatic(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_CREATEBUILTIN, SCRIPTFUNCTION_CREATEBUILTIN_SPECS_DESC);
         } else {
-            mi.invokeStatic(SCRIPTFUNCTIONIMPL_TYPE, SCRIPTFUNCTIONIMPL_MAKEFUNCTION, SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC);
+            mi.invokeStatic(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_CREATEBUILTIN, SCRIPTFUNCTION_CREATEBUILTIN_DESC);
         }
 
         if (arityFound) {
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java
index 2661e09..b47877d 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java
@@ -38,9 +38,8 @@
 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;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_INIT_DESC3;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_INIT_DESC4;
-import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_TYPE;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_INIT_DESC3;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_INIT_DESC4;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY_DESC;
 import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETPROTOTYPE;
@@ -55,7 +54,7 @@
 import jdk.internal.org.objectweb.asm.Handle;
 
 /**
- * This class generates constructor class for a @ClassInfo annotated class.
+ * This class generates constructor class for a @ScriptClass annotated class.
  *
  */
 public class ConstructorGenerator extends ClassGenerator {
@@ -75,8 +74,8 @@
     }
 
     byte[] getClassBytes() {
-        // new class extensing from ScriptObject
-        final String superClass = (constructor != null)? SCRIPTFUNCTIONIMPL_TYPE : SCRIPTOBJECT_TYPE;
+        // new class extending from ScriptObject
+        final String superClass = (constructor != null)? SCRIPTFUNCTION_TYPE : SCRIPTOBJECT_TYPE;
         cw.visit(V1_7, ACC_FINAL, className, null, superClass, null);
         if (memberCount > 0) {
             // add fields
@@ -152,6 +151,7 @@
         }
 
         if (constructor != null) {
+            initPrototype(mi);
             final int arity = constructor.getArity();
             if (arity != MemberInfo.DEFAULT_ARITY) {
                 mi.loadThis();
@@ -181,8 +181,8 @@
             loadMap(mi);
         } else {
             // call Function.<init>
-            superClass = SCRIPTFUNCTIONIMPL_TYPE;
-            superDesc = (memberCount > 0) ? SCRIPTFUNCTIONIMPL_INIT_DESC4 : SCRIPTFUNCTIONIMPL_INIT_DESC3;
+            superClass = SCRIPTFUNCTION_TYPE;
+            superDesc = (memberCount > 0) ? SCRIPTFUNCTION_INIT_DESC4 : SCRIPTFUNCTION_INIT_DESC3;
             mi.loadLiteral(constructor.getName());
             mi.visitLdcInsn(new Handle(H_INVOKESTATIC, scriptClassInfo.getJavaName(), constructor.getJavaName(), constructor.getJavaDesc()));
             loadMap(mi);
@@ -193,6 +193,7 @@
     }
 
     private void initFunctionFields(final MethodGenerator mi) {
+        assert memberCount > 0;
         for (final MemberInfo memInfo : scriptClassInfo.getMembers()) {
             if (!memInfo.isConstructorFunction()) {
                 continue;
@@ -204,37 +205,39 @@
     }
 
     private void initDataFields(final MethodGenerator mi) {
-         for (final MemberInfo memInfo : scriptClassInfo.getMembers()) {
-            if (!memInfo.isConstructorProperty() || memInfo.isFinal()) {
-                continue;
-            }
-            final Object value = memInfo.getValue();
-            if (value != null) {
-                mi.loadThis();
-                mi.loadLiteral(value);
-                mi.putField(className, memInfo.getJavaName(), memInfo.getJavaDesc());
-            } else if (!memInfo.getInitClass().isEmpty()) {
-                final String clazz = memInfo.getInitClass();
-                mi.loadThis();
-                mi.newObject(clazz);
-                mi.dup();
-                mi.invokeSpecial(clazz, INIT, DEFAULT_INIT_DESC);
-                mi.putField(className, memInfo.getJavaName(), memInfo.getJavaDesc());
-            }
+        assert memberCount > 0;
+        for (final MemberInfo memInfo : scriptClassInfo.getMembers()) {
+           if (!memInfo.isConstructorProperty() || memInfo.isFinal()) {
+               continue;
+           }
+           final Object value = memInfo.getValue();
+           if (value != null) {
+               mi.loadThis();
+               mi.loadLiteral(value);
+               mi.putField(className, memInfo.getJavaName(), memInfo.getJavaDesc());
+           } else if (!memInfo.getInitClass().isEmpty()) {
+               final String clazz = memInfo.getInitClass();
+               mi.loadThis();
+               mi.newObject(clazz);
+               mi.dup();
+               mi.invokeSpecial(clazz, INIT, DEFAULT_INIT_DESC);
+               mi.putField(className, memInfo.getJavaName(), memInfo.getJavaDesc());
+           }
         }
+    }
 
-        if (constructor != null) {
-            mi.loadThis();
-            final String protoName = scriptClassInfo.getPrototypeClassName();
-            mi.newObject(protoName);
-            mi.dup();
-            mi.invokeSpecial(protoName, INIT, DEFAULT_INIT_DESC);
-            mi.dup();
-            mi.loadThis();
-            mi.invokeStatic(PROTOTYPEOBJECT_TYPE, PROTOTYPEOBJECT_SETCONSTRUCTOR,
-                    PROTOTYPEOBJECT_SETCONSTRUCTOR_DESC);
-            mi.invokeVirtual(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_SETPROTOTYPE, SCRIPTFUNCTION_SETPROTOTYPE_DESC);
-        }
+    private void initPrototype(final MethodGenerator mi) {
+        assert constructor != null;
+        mi.loadThis();
+        final String protoName = scriptClassInfo.getPrototypeClassName();
+        mi.newObject(protoName);
+        mi.dup();
+        mi.invokeSpecial(protoName, INIT, DEFAULT_INIT_DESC);
+        mi.dup();
+        mi.loadThis();
+        mi.invokeStatic(PROTOTYPEOBJECT_TYPE, PROTOTYPEOBJECT_SETCONSTRUCTOR,
+                PROTOTYPEOBJECT_SETCONSTRUCTOR_DESC);
+        mi.invokeVirtual(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_SETPROTOTYPE, SCRIPTFUNCTION_SETPROTOTYPE_DESC);
     }
 
     /**
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/Main.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/Main.java
index 7c8439b..554c09e 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/Main.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/Main.java
@@ -134,7 +134,7 @@
                 String simpleName = inFile.getName();
                 simpleName = simpleName.substring(0, simpleName.indexOf(".class"));
 
-                if (sci.getPrototypeMemberCount() > 0) {
+                if (sci.isPrototypeNeeded()) {
                     // generate prototype class
                     final PrototypeGenerator protGen = new PrototypeGenerator(sci);
                     buf = protGen.getClassBytes();
@@ -146,7 +146,7 @@
                     }
                 }
 
-                if (sci.getConstructorMemberCount() > 0 || sci.getConstructor() != null) {
+                if (sci.isConstructorNeeded()) {
                     // generate constructor class
                     final ConstructorGenerator consGen = new ConstructorGenerator(sci);
                     buf = consGen.getClassBytes();
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java
index cc3524d..a868ada 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java
@@ -161,7 +161,7 @@
     }
 
     /**
-     * Tag something as optimitic builtin or not
+     * Tag something as optimistic builtin or not
      * @param isOptimistic boolean, true if builtin constructor
      */
     public void setIsOptimistic(final boolean isOptimistic) {
@@ -178,7 +178,7 @@
     }
 
     /**
-     * Set thre SpecializedFunction link logic class for specializations, i.e. optimistic
+     * Set the SpecializedFunction link logic class for specializations, i.e. optimistic
      * builtins
      * @param linkLogicClass link logic class
      */
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java
index 8eb19b7..80308ac 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java
@@ -42,7 +42,7 @@
 import java.io.IOException;
 
 /**
- * This class generates prototype class for a @ClassInfo annotated class.
+ * This class generates prototype class for a @ScriptClass annotated class.
  *
  */
 public class PrototypeGenerator extends ClassGenerator {
@@ -57,7 +57,7 @@
     }
 
     byte[] getClassBytes() {
-        // new class extensing from ScriptObject
+        // new class extending from ScriptObject
         cw.visit(V1_7, ACC_FINAL | ACC_SUPER, className, null, PROTOTYPEOBJECT_TYPE, null);
         if (memberCount > 0) {
             // add fields
@@ -124,8 +124,6 @@
         if (memberCount > 0) {
             // call "super(map$)"
             mi.getStatic(className, PROPERTYMAP_FIELD_NAME, PROPERTYMAP_DESC);
-            // make sure we use duplicated PropertyMap so that original map
-            // stays intact and so can be used for many global.
             mi.invokeSpecial(PROTOTYPEOBJECT_TYPE, INIT, SCRIPTOBJECT_INIT_DESC);
             // initialize Function type fields
             initFunctionFields(mi);
@@ -157,7 +155,7 @@
      */
     public static void main(final String[] args) throws IOException {
         if (args.length != 1) {
-            System.err.println("Usage: " + ConstructorGenerator.class.getName() + " <class>");
+            System.err.println("Usage: " + PrototypeGenerator.class.getName() + " <class>");
             System.exit(1);
         }
 
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java
index 9e3dfc1..ca9a325 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java
@@ -48,7 +48,7 @@
  *
  */
 public final class ScriptClassInfo {
-    // descriptots for various annotations
+    // descriptors for various annotations
     static final String SCRIPT_CLASS_ANNO_DESC  = Type.getDescriptor(ScriptClass.class);
     static final String CONSTRUCTOR_ANNO_DESC   = Type.getDescriptor(Constructor.class);
     static final String FUNCTION_ANNO_DESC      = Type.getDescriptor(Function.class);
@@ -126,10 +126,42 @@
         return Collections.unmodifiableList(res);
     }
 
+    boolean isConstructorNeeded() {
+        // Constructor class generation is needed if we one or
+        // more constructor properties are defined or @Constructor
+        // is defined in the class.
+        for (final MemberInfo memInfo : members) {
+            if (memInfo.getKind() == Kind.CONSTRUCTOR ||
+                memInfo.getWhere() == Where.CONSTRUCTOR) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    boolean isPrototypeNeeded() {
+        // Prototype class generation is needed if we have at least one
+        // prototype property or @Constructor defined in the class.
+        for (final MemberInfo memInfo : members) {
+            if (memInfo.getWhere() == Where.PROTOTYPE || memInfo.isConstructor()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     int getPrototypeMemberCount() {
         int count = 0;
         for (final MemberInfo memInfo : members) {
-            if (memInfo.getWhere() == Where.PROTOTYPE || memInfo.isConstructor()) {
+            switch (memInfo.getKind()) {
+                case SETTER:
+                case SPECIALIZED_FUNCTION:
+                    // SETTER was counted when GETTER was encountered.
+                    // SPECIALIZED_FUNCTION was counted as FUNCTION already.
+                    continue;
+            }
+
+            if (memInfo.getWhere() == Where.PROTOTYPE) {
                 count++;
             }
         }
@@ -139,6 +171,16 @@
     int getConstructorMemberCount() {
         int count = 0;
         for (final MemberInfo memInfo : members) {
+            switch (memInfo.getKind()) {
+                case CONSTRUCTOR:
+                case SETTER:
+                case SPECIALIZED_FUNCTION:
+                    // SETTER was counted when GETTER was encountered.
+                    // Constructor and constructor SpecializedFunctions
+                    // are not added as members and so not counted.
+                    continue;
+            }
+
             if (memInfo.getWhere() == Where.CONSTRUCTOR) {
                 count++;
             }
@@ -149,6 +191,14 @@
     int getInstancePropertyCount() {
         int count = 0;
         for (final MemberInfo memInfo : members) {
+            switch (memInfo.getKind()) {
+                case SETTER:
+                case SPECIALIZED_FUNCTION:
+                    // SETTER was counted when GETTER was encountered.
+                    // SPECIALIZED_FUNCTION was counted as FUNCTION already.
+                    continue;
+            }
+
             if (memInfo.getWhere() == Where.INSTANCE) {
                 count++;
             }
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java
index aa47762..62fa339 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java
@@ -118,7 +118,7 @@
                     addScriptMember(memInfo);
 
                     return new AnnotationVisitor(Opcodes.ASM4, delegateAV) {
-                        // These could be "null" if values are not suppiled,
+                        // These could be "null" if values are not supplied,
                         // in which case we have to use the default values.
                         private String  name;
                         private Integer attributes;
@@ -194,7 +194,7 @@
 
                     final MemberInfo memInfo = new MemberInfo();
 
-                    //annokind == e.g. GETTER or SPECIALIZED_FUNCTION
+                    // annoKind == GETTER or SPECIALIZED_FUNCTION
                     memInfo.setKind(annoKind);
                     memInfo.setJavaName(methodName);
                     memInfo.setJavaDesc(methodDesc);
@@ -203,7 +203,7 @@
                     addScriptMember(memInfo);
 
                     return new AnnotationVisitor(Opcodes.ASM4, delegateAV) {
-                        // These could be "null" if values are not suppiled,
+                        // These could be "null" if values are not supplied,
                         // in which case we have to use the default values.
                         private String  name;
                         private Integer attributes;
@@ -288,9 +288,7 @@
                                         where = Where.PROTOTYPE;
                                         break;
                                     case SPECIALIZED_FUNCTION:
-                                        if (isSpecializedConstructor) {
-                                            where = Where.CONSTRUCTOR;
-                                        }
+                                        where = isSpecializedConstructor? Where.CONSTRUCTOR : Where.PROTOTYPE;
                                         //fallthru
                                     default:
                                         break;
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java
index 0d6a9e3..354289c 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java
@@ -65,7 +65,6 @@
  * 2) add "Map" type static field named "$map".
  * 3) add static initializer block to initialize map.
  */
-
 public class ScriptClassInstrumentor extends ClassVisitor {
     private final ScriptClassInfo scriptClassInfo;
     private final int memberCount;
@@ -267,7 +266,7 @@
      */
     public static void main(final String[] args) throws IOException {
         if (args.length != 1) {
-            System.err.println("Usage: " + ScriptClassInfoCollector.class.getName() + " <class>");
+            System.err.println("Usage: " + ScriptClassInstrumentor.class.getName() + " <class>");
             System.exit(1);
         }
 
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java
index 8656a42..6669514 100644
--- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java
+++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java
@@ -31,10 +31,9 @@
 import java.util.Collections;
 import java.util.List;
 import jdk.internal.org.objectweb.asm.Type;
-import jdk.nashorn.internal.objects.PrototypeObject;
-import jdk.nashorn.internal.objects.ScriptFunctionImpl;
 import jdk.nashorn.internal.runtime.AccessorProperty;
 import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.PrototypeObject;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.Specialization;
@@ -88,7 +87,6 @@
     static final Type TYPE_PROPERTYMAP        = Type.getType(PropertyMap.class);
     static final Type TYPE_PROTOTYPEOBJECT    = Type.getType(PrototypeObject.class);
     static final Type TYPE_SCRIPTFUNCTION     = Type.getType(ScriptFunction.class);
-    static final Type TYPE_SCRIPTFUNCTIONIMPL = Type.getType(ScriptFunctionImpl.class);
     static final Type TYPE_SCRIPTOBJECT       = Type.getType(ScriptObject.class);
 
     static final String PROTOTYPE_SUFFIX = "$Prototype";
@@ -122,17 +120,14 @@
     static final String SCRIPTFUNCTION_SETARITY_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE);
     static final String SCRIPTFUNCTION_SETPROTOTYPE = "setPrototype";
     static final String SCRIPTFUNCTION_SETPROTOTYPE_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_OBJECT);
-
-    // ScriptFunctionImpl
-    static final String SCRIPTFUNCTIONIMPL_TYPE = TYPE_SCRIPTFUNCTIONIMPL.getInternalName();
-    static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION = "makeFunction";
-    static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC =
+    static final String SCRIPTFUNCTION_CREATEBUILTIN = "createBuiltin";
+    static final String SCRIPTFUNCTION_CREATEBUILTIN_DESC =
         Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE);
-    static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC =
+    static final String SCRIPTFUNCTION_CREATEBUILTIN_SPECS_DESC =
         Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE, TYPE_SPECIALIZATION_ARRAY);
-    static final String SCRIPTFUNCTIONIMPL_INIT_DESC3 =
+    static final String SCRIPTFUNCTION_INIT_DESC3 =
         Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_SPECIALIZATION_ARRAY);
-    static final String SCRIPTFUNCTIONIMPL_INIT_DESC4 =
+    static final String SCRIPTFUNCTION_INIT_DESC4 =
         Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_PROPERTYMAP, TYPE_SPECIALIZATION_ARRAY);
 
     // ScriptObject
diff --git a/docs/DEVELOPER_README b/docs/DEVELOPER_README
index 5550b90..faff28c 100644
--- a/docs/DEVELOPER_README
+++ b/docs/DEVELOPER_README
@@ -63,16 +63,19 @@
 See the description of the codegen logger below.
 
 
-SYSTEM PROPERTY: -Dnashorn.fields.objects
+SYSTEM PROPERTY: -Dnashorn.fields.objects, -Dnashorn.fields.dual
 
-When this property is true, Nashorn will only use object fields for
-AccessorProperties. This means that primitive values must be boxed
-when stored in a field, which is significantly slower than using
-primitive fields.
+When the nashorn.fields.objects property is true, Nashorn will always
+use object fields for AccessorProperties, requiring boxing for all
+primitive property values. When nashorn.fields.dual is set, Nashorn
+will always use dual long/object fields, which allows primitives to be
+stored without boxing. When neither system property is set, Nashorn
+chooses a setting depending on the optimistic types setting (dual
+fields when optimistic types are enabled, object-only fields otherwise).
 
-By default, Nashorn uses dual object and long fields. Ints are
-represented as the 32 low bits of the long fields. Doubles are
-represented as the doubleToLongBits of their value. This way a
+With dual fields, Nashorn uses long fields to store primitive values.
+Ints are represented as the 32 low bits of the long fields. Doubles
+are represented as the doubleToLongBits of their value. This way a
 single field can be used for all primitive types. Packing and
 unpacking doubles to their bit representation is intrinsified by
 the JVM and extremely fast.
diff --git a/make/build.xml b/make/build.xml
index a7539f4..9e62722 100644
--- a/make/build.xml
+++ b/make/build.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <!--
- Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
  This code is free software; you can redistribute it and/or modify it
@@ -189,7 +189,7 @@
     <mkdir dir="${fxshell.classes.dir}"/>
     <javac srcdir="${fxshell.dir}"
            destdir="${fxshell.classes.dir}"
-           classpath="${dist.jar}:${javac.classpath}"
+           classpath="${dist.jar}${path.separator}${javac.classpath}"
            debug="${javac.debug}"
            encoding="${javac.encoding}"
            includeantruntime="false">
@@ -209,10 +209,11 @@
     </jar>
   </target>
 
+  <!-- generate javadoc for all Nashorn and ASM classes -->
   <target name="javadoc" depends="jar">
-    <javadoc destdir="${dist.javadoc.dir}" use="yes" overview="src/overview.html" 
+    <javadoc destdir="${dist.javadoc.dir}" use="yes" overview="${src.dir}/overview.html" 
         extdirs="${nashorn.ext.path}" windowtitle="${nashorn.product.name} ${nashorn.version}"
-        additionalparam="-quiet" failonerror="true">
+        additionalparam="-quiet" failonerror="true" useexternalfile="true">
       <classpath>
         <pathelement location="${build.classes.dir}"/>
       </classpath>
@@ -226,10 +227,23 @@
     </javadoc>
   </target>
 
+  <!-- generate javadoc for Nashorn classes -->
+  <target name="javadocnh" depends="jar">
+    <javadoc destdir="${dist.javadoc.dir}" use="yes" overview="${src.dir}/overview.html"
+        extdirs="${nashorn.ext.path}" windowtitle="${nashorn.product.name} ${nashorn.version}"
+        additionalparam="-quiet" failonerror="true" useexternalfile="true">
+      <classpath>
+        <pathelement location="${build.classes.dir}"/>
+      </classpath>
+      <fileset dir="${src.dir}" includes="**/*.java"/>
+      <link href="http://docs.oracle.com/javase/8/docs/api/"/>
+    </javadoc>
+  </target>
+
   <!-- generate javadoc only for nashorn extension api classes -->
   <target name="javadocapi" depends="jar">
     <javadoc destdir="${dist.javadoc.dir}" use="yes" extdirs="${nashorn.ext.path}" 
-        windowtitle="${nashorn.product.name}" additionalparam="-quiet" failonerror="true">
+        windowtitle="${nashorn.product.name}" additionalparam="-quiet" failonerror="true" useexternalfile="true">
       <classpath>
         <pathelement location="${build.classes.dir}"/>
       </classpath>
@@ -238,7 +252,6 @@
     </javadoc>
   </target>
 
-
   <!-- generate shell.html for shell tool documentation -->
   <target name="shelldoc" depends="jar">
     <java classname="${nashorn.shell.tool}" dir="${basedir}" output="${dist.dir}/shell.html" failonerror="true" fork="true">
@@ -267,8 +280,8 @@
     <javac srcdir="${test.src.dir}"
            destdir="${build.test.classes.dir}"
            classpath="${javac.test.classpath}"
-           source="${javac.source}"
-           target="${javac.target}"
+           source="${test.javac.source}"
+           target="${test.javac.target}"
            debug="${javac.debug}"
            encoding="${javac.encoding}"
            includeantruntime="false" fork="true">
@@ -282,12 +295,12 @@
        <fileset dir="${test.src.dir}/META-INF/services/"/>
     </copy>
 
-    <copy todir="${build.test.classes.dir}/jdk/nashorn/internal/runtime/resources">
-       <fileset dir="${test.src.dir}/jdk/nashorn/internal/runtime/resources"/>
+    <copy todir="${build.test.classes.dir}/jdk/nashorn/internal/runtime/test/resources">
+       <fileset dir="${test.src.dir}/jdk/nashorn/internal/runtime/test/resources"/>
     </copy>
 
-    <copy todir="${build.test.classes.dir}/jdk/nashorn/api/scripting/resources">
-       <fileset dir="${test.src.dir}/jdk/nashorn/api/scripting/resources"/>
+    <copy todir="${build.test.classes.dir}/jdk/nashorn/api/scripting/test/resources">
+       <fileset dir="${test.src.dir}/jdk/nashorn/api/scripting/test/resources"/>
     </copy>
 
     <!-- tests that check nashorn internals and internal API -->
@@ -343,6 +356,13 @@
     permission java.util.PropertyPermission "nashorn.test.*", "read";
 };
 
+grant codeBase "file:/${basedir}/test/script/basic/apply_to_call/*" {
+    permission java.io.FilePermission "${basedir}/test/script/-", "read";
+    permission java.io.FilePermission "$${user.dir}", "read";
+    permission java.util.PropertyPermission "user.dir", "read";
+    permission java.util.PropertyPermission "nashorn.test.*", "read";
+};
+
 grant codeBase "file:/${basedir}/test/script/basic/parser/*" {
     permission java.io.FilePermission "${basedir}/test/script/-", "read";
     permission java.io.FilePermission "$${user.dir}", "read";
@@ -388,19 +408,19 @@
   </target>
 
   <target name="check-testng" unless="testng.available">
-    <echo message="WARNING: TestNG not available, will not run tests. Please copy testng.jar under test/lib directory."/>
+    <echo message="WARNING: TestNG not available, will not run tests. Please copy testng.jar under ${test.lib} directory."/>
   </target>
 
   <!-- only to be invoked as dependency of "test" target -->
   <target name="-test-classes-all" depends="jar" unless="test.class">
       <fileset id="test.classes" dir="${build.test.classes.dir}">
-          <include name="**/api/javaaccess/*Test.class"/>
-          <include name="**/api/scripting/*Test.class"/>
-          <include name="**/codegen/*Test.class"/>
-          <include name="**/parser/*Test.class"/>
-          <include name="**/runtime/*Test.class"/>
-          <include name="**/runtime/regexp/*Test.class"/>
-          <include name="**/runtime/regexp/joni/*Test.class"/>
+          <include name="**/api/javaaccess/test/*Test.class"/>
+          <include name="**/api/scripting/test/*Test.class"/>
+          <include name="**/codegen/test/*Test.class"/>
+          <include name="**/parser/test/*Test.class"/>
+          <include name="**/runtime/test/*Test.class"/>
+          <include name="**/runtime/regexp/test/*Test.class"/>
+          <include name="**/runtime/regexp/joni/test/*Test.class"/>
           <include name="**/framework/*Test.class"/>
      </fileset>
   </target>
@@ -460,7 +480,7 @@
     </testng>
   </target>
 
-  <target name="test" depends="test-pessimistic, test-optimistic"/>
+  <target name="test" depends="get-testng, javadocnh, test-pessimistic, test-optimistic"/>
 
   <target name="test-optimistic" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
     <echo message="Running test suite in OPTIMISTIC mode..."/>
@@ -490,7 +510,7 @@
     <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>
 
-  <target name="testjfx" depends="jar, check-jemmy.jfx.testng, compile-test" if="jemmy.jfx.testng.available">
+  <target name="testjfx" depends="jar, get-testng, check-jemmy.jfx.testng, compile-test" if="jemmy.jfx.testng.available">
     <fileset id="test.classes" dir="${build.test.classes.dir}">
        <include name="**/framework/*Test.class"/>
     </fileset>
@@ -518,7 +538,7 @@
     </testng>
   </target>
 
-  <target name="testmarkdown" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+  <target name="testmarkdown" depends="jar, get-testng, 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>
@@ -537,7 +557,7 @@
     </testng>
   </target>
 
-  <target name="test262" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+  <target name="test262" depends="jar, get-testng, 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>
@@ -561,7 +581,7 @@
 
   <target name="test262parallel" depends="test262-parallel"/>
 
-  <target name="test262-parallel" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available">
+  <target name="test262-parallel" depends="jar, get-testng, 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}" fork="true">
       <jvmarg line="${ext.class.path}"/>
@@ -580,7 +600,7 @@
 
   <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">
+  <target name="test-parallel" depends="jar, get-testng, 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"
@@ -685,7 +705,7 @@
   </target>
 
   <!-- get all external test scripts -->
-  <target name="externals" depends="init, check-external-tests, get-test262, get-octane, get-sunspider">
+  <target name="externals" depends="init, check-external-tests, get-test262, get-octane, get-sunspider, get-testng">
     <!-- make external test dir -->
     <mkdir dir="${test.external.dir}"/>
 
@@ -710,8 +730,8 @@
 
     <!-- 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"/>
+    <get src="https://raw.githubusercontent.com/showdownjs/showdown/0.5.4/src/showdown.js" dest="${test.external.dir}/showdown" skipexisting="true" ignoreerrors="true"/>
+    <get src="https://raw.githubusercontent.com/showdownjs/showdown/0.5.4/src/extensions/table.js" dest="${test.external.dir}/showdown" skipexisting="true" ignoreerrors="true"/>
 
   </target>
 
@@ -721,12 +741,20 @@
   <!-- run all perf tests -->
   <target name="perf" depends="externals, update-externals, sunspider, octane"/>
 
-  <!-- run all tests -->
-  <target name="exit-if-no-testng" depends="init, check-testng" unless="${testng.available}">
-     <fail message="Exiting.."/>
+  <!-- download and install testng.jar -->
+  <target name="get-testng" depends="prepare" unless="testng.available">
+    <get src="http://testng.org/testng-6.8.zip" dest="${test.lib}" skipexisting="true" ignoreerrors="true"/>
+    <unzip src="${test.lib}${file.separator}testng-6.8.zip" dest="${test.lib}">
+      <patternset>
+        <include name="testng-6.8/testng-6.8.jar"/>
+      </patternset>
+    </unzip>
+    <move file="${test.lib}${file.separator}testng-6.8${file.separator}testng-6.8.jar" tofile="${test.lib}${file.separator}testng.jar"/>
+    <delete dir="${test.lib}${file.separator}testng-6.8"/>
   </target>
 
-  <target name="alltests" depends="exit-if-no-testng, externals, update-externals, test, test262parallel, perf"/>
+  <!-- run all tests -->
+  <target name="alltests" depends="get-testng, externals, update-externals, test, test262parallel, testmarkdown, perf"/>
 
   <import file="build-benchmark.xml"/>
 
diff --git a/make/project.properties b/make/project.properties
index 9d36fbd..1632f2c 100644
--- a/make/project.properties
+++ b/make/project.properties
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
 # 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,6 +30,8 @@
 build.compiler=modern
 javac.source=1.7
 javac.target=1.7
+test.javac.source=1.8
+test.javac.target=1.8
 
 # nashorn version information
 nashorn.version=0.1
@@ -77,8 +79,11 @@
 # 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
 
+# test library location
+test.lib=${basedir}${file.separator}test${file.separator}lib
+
 # jars refererred
-file.reference.testng.jar=test/lib/testng.jar
+file.reference.testng.jar=${test.lib}${file.separator}testng.jar
 
 # Set testng verbose level
 # From TestNG docs: "the verbosity level (0 to 10 where 10 is most detailed) 
@@ -105,8 +110,8 @@
 javac.classpath=\
     ${build.classes.dir}
 javac.test.classpath=\
-    ${build.classes.dir}:\
-    ${build.test.classes.dir}:\
+    ${build.classes.dir}${path.separator}\
+    ${build.test.classes.dir}${path.separator}\
     ${file.reference.testng.jar}
 
 meta.inf.dir=${src.dir}/META-INF
@@ -237,9 +242,9 @@
     -fx \
     ${test.script.dir}${file.separator}jfx.js
 
-file.reference.jemmyfx.jar=test${file.separator}lib${file.separator}JemmyFX.jar
-file.reference.jemmycore.jar=test${file.separator}lib${file.separator}JemmyCore.jar
-file.reference.jemmyawtinput.jar=test${file.separator}lib${file.separator}JemmyAWTInput.jar
+file.reference.jemmyfx.jar=${test.lib}${file.separator}JemmyFX.jar
+file.reference.jemmycore.jar=${test.lib}${file.separator}JemmyCore.jar
+file.reference.jemmyawtinput.jar=${test.lib}${file.separator}JemmyAWTInput.jar
 file.reference.jfxrt.jar=${java.home}${file.separator}lib${file.separator}ext${file.separator}jfxrt.jar
 testjfx.run.test.classpath=\
     ${file.reference.jemmyfx.jar}${path.separator}\
@@ -253,8 +258,8 @@
 testjfx-test-sys-prop.test.fork.jvm.options=${run.test.jvmargs.main} -Xmx${run.test.xmx} -cp ${testjfx.run.test.classpath}
 
 run.test.classpath=\
-    ${file.reference.testng.jar}:\
-    ${nashorn.internal.tests.jar}:\
+    ${file.reference.testng.jar}${path.separator}\
+    ${nashorn.internal.tests.jar}${path.separator}\
     ${nashorn.api.tests.jar}
 
 src.dir=src
@@ -330,6 +335,8 @@
 
 # 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}
+# VM options for no-security script tests with @fork option - same as above but without jvmsecurityargs
+test-sys-prop-no-security.test.fork.jvm.options=${run.test.jvmargs.main} -Xmx${run.test.xmx} -cp ${run.test.classpath}
 
 # path of rhino.jar for benchmarks
 rhino.dir=
diff --git a/samples/EvalWithArbitraryThis.java b/samples/EvalWithArbitraryThis.java
new file mode 100644
index 0000000..4b9c0c7
--- /dev/null
+++ b/samples/EvalWithArbitraryThis.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+import javax.script.*;
+import jdk.nashorn.api.scripting.*;
+
+// Simple nashorn demo that evals a script with arbitrary script
+// object bound as "this" for the evaluated script.
+
+public class EvalWithArbitraryThis {
+    public static void main(String[] args) throws Exception {
+        ScriptEngineManager m = new ScriptEngineManager();
+        ScriptEngine e = m.getEngineByName("nashorn");
+        Object sobj = e.eval("( { foo: 343, bar: 'hello' } )");
+
+        // "this" bound to sobj in this eval.
+        // so it prints sobj.foo and sobj.bar.
+        ((ScriptObjectMirror)sobj).eval("print(this.foo); print(this.bar)");
+    }
+}
diff --git a/samples/LambdaAsFunc.java b/samples/LambdaAsFunc.java
new file mode 100644
index 0000000..1ed5380
--- /dev/null
+++ b/samples/LambdaAsFunc.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+import javax.script.*;
+import java.util.function.*;
+
+// example demonstrating that arbitrary Lambda can be called as function from script
+
+public class LambdaAsFunc {
+    public static void main(String[] args) throws Exception {
+        ScriptEngineManager m = new ScriptEngineManager();
+        ScriptEngine e = m.getEngineByName("nashorn");
+
+        // expose a lambda as top-level script function
+        e.put("upper", (Function<String, String>) String::toUpperCase);
+
+        // call lambda as though it is a normal script function
+        System.out.println(e.eval("upper('hello')"));
+    }
+}
diff --git a/samples/Main.asm b/samples/Main.asm
new file mode 100644
index 0000000..3c4fd5e
--- /dev/null
+++ b/samples/Main.asm
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// Simple sample to demonstrate openjdk asmtools assembler with
+// nashorn dynalink linker in a invokedynamic instruction.
+//
+// To assemble this file, use the following command:
+//
+//    java -cp <asmtools.jar> org.openjdk.asmtools.Main jasm Main.asm
+//
+// See also: https://wiki.openjdk.java.net/display/CodeTools/asmtools
+//
+// NOTE: Uses nashorn internals and so *may* break with later nashorn!
+
+super public class Main
+	version 52:0
+{
+
+
+public Method "<init>":"()V"
+	stack 1 locals 1
+{
+		aload_0;
+		invokespecial	Method java/lang/Object."<init>":"()V";
+		return;
+}
+
+public static Method main:"([Ljava/lang/String;)V"
+	stack 2 locals 2
+{
+                // List l = new ArrayList();
+		new	class java/util/ArrayList;
+		dup;
+		invokespecial	Method java/util/ArrayList."<init>":"()V";
+		astore_1;
+		aload_1;
+
+                // l.add("hello");
+		ldc	String "hello";
+		invokeinterface	InterfaceMethod java/util/List.add:"(Ljava/lang/Object;)Z",  2;
+		pop;
+
+                // l.add("world");
+		aload_1;
+		ldc	String "world";
+		invokeinterface	InterfaceMethod java/util/List.add:"(Ljava/lang/Object;)Z",  2;
+		pop;
+
+                // printLength(l);
+		aload_1;
+		invokestatic	Method printLength:"(Ljava/lang/Object;)V";
+
+                // printLength(args); // args is argument of main method
+		aload_0;
+		invokestatic	Method printLength:"(Ljava/lang/Object;)V";
+		return;
+}
+
+private static Method printLength:"(Ljava/lang/Object;)V"
+	stack 2 locals 1
+{
+		getstatic	Field java/lang/System.out:"Ljava/io/PrintStream;";
+		aload_0;
+
+                // Using nashorn embedded dynalink linker with the following invokedynamic
+                // 'length' property on a bean - arrays, lists supported
+
+                invokedynamic   InvokeDynamic REF_invokeStatic:jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;":"dyn:getProp|getElem|getMethod:length":"(Ljava/lang/Object;)Ljava/lang/Object;" int 0;
+
+                // print 'length' value
+		invokevirtual	Method java/io/PrintStream.println:"(Ljava/lang/Object;)V";
+		return;
+}
+
+} // end Class Main
diff --git a/samples/PrintToString.java b/samples/PrintToString.java
new file mode 100644
index 0000000..21f1f9e
--- /dev/null
+++ b/samples/PrintToString.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+import javax.script.*;
+import java.io.StringWriter;
+
+// simple example demonstrating capturing of "print" output
+// from script execution as a String via script engine API.
+
+public class PrintToString {
+  public static void main(String[] args) throws ScriptException {
+    ScriptEngineManager m = new ScriptEngineManager();
+    ScriptEngine e = m.getEngineByName("nashorn");
+    StringWriter sw = new StringWriter();
+    e.getContext().setWriter(sw);
+    e.eval("print('hello world')");
+    System.out.println(sw.toString());
+  }
+}
diff --git a/samples/array_removeif.js b/samples/array_removeif.js
new file mode 100644
index 0000000..68cc873
--- /dev/null
+++ b/samples/array_removeif.js
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// Sample for Collection.removeIf and Java.to
+// See http://docs.oracle.com/javase/8/docs/api/java/util/Collection.html#removeIf-java.util.function.Predicate-
+ 
+var langs = [
+    "java", "javascript",
+    "C", "C#", "C++",
+    "Erlang", "Haskell"
+];
+ 
+// convert script array to a Java List
+function asList(array) {
+    return Java.to(array, java.util.List);
+}
+ 
+// remove elements that satisfy a predicate
+// using Collection.removeIf(Predicate)
+asList(langs).removeIf(
+    function(s) s.startsWith("C"));
+ 
+// print modified array
+print(langs);
diff --git a/samples/autoimports.js b/samples/autoimports.js
new file mode 100644
index 0000000..85683f5
--- /dev/null
+++ b/samples/autoimports.js
@@ -0,0 +1,163 @@
+# autoimports script requires -scripting mode
+
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+/*
+ * It is tedious to import Java classes used in a script. Sometimes it is easier
+ * use simple names of java classes and have a script auto import Java classes. 
+ * You can load this script at the start of an interactive jjs session or at the
+ * start of your script. This script defines a __noSuchProperty__ hook to auto 
+ * import Java classes as needed and when they are referred to for the first time
+ * in your script. You can also call the "autoimports" function to print script 
+ * statements that you need to use in your script, i.e., have the function generate
+ * a script to import Java classes used by your script so far. After running your
+ * script, you can call autoimports to get the exact Java imports you need and replace
+ * the autoimports load with the generated import statements (to avoid costly init of
+ * the autoimports script).
+ */
+
+(function() {
+    var ArrayList = Java.type("java.util.ArrayList");
+    var HashMap = Java.type("java.util.HashMap");
+    var JarFile = Java.type("java.util.jar.JarFile");
+    var File = Java.type("java.io.File");
+    var Files = Java.type("java.nio.file.Files");
+    var FileSystems = Java.type("java.nio.file.FileSystems");
+    var System = Java.type("java.lang.System");
+    var URI = Java.type("java.net.URI");
+
+    // initialize a class to package map by iterating all
+    // classes available in the system by walking through "jrt fs"
+
+    var clsToPkg = new HashMap();
+
+    // locate rt.jar from sun.boot.class.path
+    function findRtJar() {
+        var paths = System.getProperty("sun.boot.class.path").split(File.pathSeparator);
+        for each (var p in paths) {
+            if (p.endsWith("rt.jar") && new File(p).exists()) {
+                return p;
+            }
+        }
+    }
+
+
+    function addToClsToPkg(c, p) {
+        if (clsToPkg.containsKey(c)) {
+            var val = clsToPkg.get(c);
+            if (val instanceof ArrayList) {
+                val.add(p);
+            } else {
+                var al = new ArrayList();
+                al.add(val);
+                al.add(p);
+                clsToPkg.put(c, al);
+            }
+        } else {
+            clsToPkg.put(c, p);
+        }
+    }
+
+    // handle collision and allow user to choose package
+    function getPkgOfCls(c) {
+        var val = clsToPkg.get(c);
+        if (val instanceof ArrayList) {
+            var count = 1;
+            print("Multiple matches for " + c + ", choose package:");
+            for each (var v in val) {
+                print(count + ". " + v);
+                count++;
+            }
+            var choice = parseInt(readLine());
+            if (isNaN(choice) || choice < 1 || choice > val.size()) {
+                print("invalid choice: " + choice);
+                return undefined;
+            }
+            return val.get(choice - 1);
+        } else {
+            return val;
+        }
+    }
+
+    var rtJar = findRtJar();
+    var stream = new JarFile(rtJar).stream();
+    try {
+        stream.forEach(
+            function(entry) {
+                var str = entry.name;
+                if (str.endsWith(".class")) {
+                    if (str.startsWith("java") ||
+                        str.startsWith("javax") ||
+                        str.startsWith("org")) {
+                        var lastIdx = str.lastIndexOf('/');
+                        if (lastIdx != -1) {
+                            var pkg = str.substring(0, lastIdx).replaceAll('/', '.');
+                            var cls = str.substring(lastIdx + 1, str.lastIndexOf(".class"));
+                            addToClsToPkg(cls, pkg);
+                        }
+                    }
+                }
+            });
+    } finally {
+        stream.close();
+    }
+
+    var imports = new ArrayList();
+    var global = this;
+    var oldNoSuchProp = global.__noSuchProperty__;
+    this.__noSuchProperty__ = function(name) {
+        'use strict';
+
+        if (clsToPkg.containsKey(name)) {
+            var pkg = getPkgOfCls(name);
+            if (pkg) {
+                var clsName = pkg + "." + name;
+                imports.add("var " + name + " = Java.type('" + clsName + "');");
+                return global[name] = Java.type(clsName);
+            }
+        } else if (typeof oldNoSuchProp == 'function') {
+            return oldNoSuchProp.call(this, name);
+        }
+
+        if (typeof this == 'undefined') {
+            throw new ReferenceError(name);
+        } else {
+            return undefined;
+        }
+    }
+
+    this.autoimports = function() {
+        for each (var im in imports) {
+            print(im);
+        }
+    }
+})();
diff --git a/samples/bind_on_java.js b/samples/bind_on_java.js
new file mode 100644
index 0000000..e905a39
--- /dev/null
+++ b/samples/bind_on_java.js
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// sample to demonstrate calling Function.prototype.bind on Java methods.
+
+var DoubleStream = java.util.stream.DoubleStream;
+var r = new java.util.Random();
+
+// bind "this" for nextGaussian method of Random class
+var next = Function.bind.call(r.nextGaussian, r);
+
+// next is used as no argument "function"
+DoubleStream
+    .generate(function() next())
+    .limit(100)
+    .forEach(print);
diff --git a/samples/browser_dom.js b/samples/browser_dom.js
index 94324c7..789801f 100644
--- a/samples/browser_dom.js
+++ b/samples/browser_dom.js
@@ -1,4 +1,4 @@
-#// Usage: jjs -fx browser.js
+#// Usage: jjs -fx browser_dom.js
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
@@ -32,7 +32,7 @@
  */
 
 if (!$OPTIONS._fx) {
-    print("Usage: jjs -fx browser.js");
+    print("Usage: jjs -fx browser_dom.js");
     exit(1);
 }
 
@@ -40,7 +40,6 @@
 var ChangeListener = Java.type("javafx.beans.value.ChangeListener");
 var Scene     = Java.type("javafx.scene.Scene");
 var WebView   = Java.type("javafx.scene.web.WebView");
-var EventListener = Java.type("org.w3c.dom.events.EventListener");
 
 // JavaFX start method
 function start(stage) {
@@ -74,10 +73,10 @@
                var btn = document.createElement("button");
                var n = 0;
                // attach a button handler - nashorn function!
-               btn.onclick = new EventListener(function() {
+               btn.onclick = function() {
                    n++; print("You clicked " + n + " time(s)");
                    print("you clicked OK " + wv.engine.executeScript("okCount"));
-               });
+               };
                // attach text to button
                var t = document.createTextNode("Click Me!"); 
                btn.appendChild(t);
diff --git a/samples/call_bind_java.js b/samples/call_bind_java.js
new file mode 100644
index 0000000..d67d5da
--- /dev/null
+++ b/samples/call_bind_java.js
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// Sample demonstrating calling Java methods like normal
+// functions. Bound instance methods, static methods can be
+// called like normal script functions.
+
+// Java types used
+var Files = Java.type("java.nio.file.Files");
+var FileSystems = Java.type("java.nio.file.FileSystems");
+var System = Java.type("java.lang.System");
+
+var fs = FileSystems.default;
+var bind = Function.prototype.bind;
+
+// Java methods as "functions"
+
+// Java method with bound "this"
+var Path = bind.call(fs.getPath, fs);
+// Java static method
+var Property = System.getProperty;
+
+// call Java static methods and bound instance methods
+// like normal script functions.
+
+var root = Path("/");
+// print URI for root dir
+print(root.toUri());
+var home = Path(Property("user.home"));
+// list home directory
+Files.walk(home).forEach(print);
diff --git a/samples/check_nashorn.js b/samples/check_nashorn.js
new file mode 100644
index 0000000..feeb30b
--- /dev/null
+++ b/samples/check_nashorn.js
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// check if script is being run using nashorn script engine
+function isNashorn() {
+  try {
+    // "engine" variable is of type javax.script.ScriptEngine is defined
+    // by nashorn jsr-223 engine. Check the name of the engine from
+    // javax.script.ScriptEngineFactory associated
+    
+    return engine.factory.engineName.contains("Nashorn");
+  } catch (e) {
+    // if engine or any of the properties are undefined
+    // then script is not being run using nashorn.
+    return false;
+  }
+}
diff --git a/samples/console.js b/samples/console.js
new file mode 100644
index 0000000..ba1fb93
--- /dev/null
+++ b/samples/console.js
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+/**
+ * Simple Web Console-like support for Nashorn. In addition to
+ * Web console object methods, this console add methods of
+ * java.io.Console as well. Note:not all web console methods are 
+ * implemented but useful subset is implemented.
+ *
+ * See also: https://developer.mozilla.org/en/docs/Web/API/console
+ */
+
+
+if (typeof console == 'undefined') {
+
+(function() {
+    var LocalDateTime = Java.type("java.time.LocalDateTime");
+    var System = Java.type("java.lang.System");
+    var jconsole = System.console();
+
+    // add a new global variable called "console"
+    this.console = {
+    };
+
+    function addConsoleMethods() {
+        // expose methods of java.io.Console as an extension
+        var placeholder = "-*-";
+        // put a placeholder for each name from java.lang.Object
+        var objMethods = Object.bindProperties({}, new java.lang.Object());
+        for (var m in objMethods) {
+            console[m] = placeholder;
+        }
+
+        // bind only the methods of java.io.Console
+        // This bind will skip java.lang.Object methods as console
+        // has properties of same name.
+        Object.bindProperties(console, jconsole);
+
+        // Now, delete java.lang.Object methods
+        for (var m in console) {
+            if (console[m] == placeholder) {
+                delete console[m];
+            }
+        }
+    }
+
+    addConsoleMethods();
+
+    function consoleLog(type, msg) {
+        // print type of message, then time.
+        jconsole.format("%s [%s] ", type, LocalDateTime.now().toString());
+        if (typeof msg == 'string') {
+            jconsole.format(msg + "\n", Array.prototype.slice.call(arguments, 2));
+        } else {
+            // simple space separated values and newline at the end
+            var arr = Array.prototype.slice.call(arguments, 1);
+            jconsole.format("%s\n", arr.join(" "));
+        }
+    }
+
+    console.toString = function() "[object Console]";
+
+    // web console functions
+
+    console.assert = function(expr) {
+        if (! expr) {
+            arguments[0] = "Assertion Failed:"; 
+            consoleLog.apply(console, arguments);
+            // now, stack trace at the end
+            jconsole.format("%s\n", new Error().stack);
+        }
+    };
+
+    // dummy clear to avoid error!
+    console.clear = function() {};
+
+    var counter = {
+        get: function(label) {
+            if (! this[label]) {
+                return this[label] = 1;
+            } else {
+                return ++this[label];
+            }
+        }
+    };
+   
+    // counter 
+    console.count = function(label) {
+        label = label? String(label) : "<no label>";
+        jconsole.format("%s: %d\n",label, counter.get(label).intValue());
+    }
+
+    // logging
+    console.error = consoleLog.bind(jconsole, "ERROR");
+    console.info = consoleLog.bind(jconsole, "INFO");
+    console.log = console.info;
+    console.debug = console.log;
+    console.warn = consoleLog.bind(jconsole, "WARNING");
+
+    // print stack trace
+    console.trace = function() {
+        jconsole.format("%s\n", new Error().stack);
+    };
+})();
+
+}
diff --git a/samples/consoleuse.js b/samples/consoleuse.js
new file mode 100644
index 0000000..7927d70
--- /dev/null
+++ b/samples/consoleuse.js
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+load(__DIR__ + "console.js");
+
+console.log("consoleuse.js started!");
+
+function func() {
+    console.count("func");
+}
+
+
+func();
+func();
+func();
+func();
+
+// java.io.Console method
+console.readPassword("passworld please: ");
+console.error("Big error: %s!", "you revealed your password!");
+console.warn("You've done this %d times", 345);
+console.assert(arguments.length != 0, "no arguments!");
+
+// java.io.Console methods
+var str = console.readLine("enter something: ");
+console.printf("you entered: %s\n", str);
+
diff --git a/samples/dateconversion.js b/samples/dateconversion.js
new file mode 100644
index 0000000..a8abda6
--- /dev/null
+++ b/samples/dateconversion.js
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// Converting between #javascript Date and #java8 LocalDateTime with #nashorn
+
+// JavaScript Date with current time
+var d = new Date();
+print(d);
+ 
+// Java 8 java.time classes used
+var Instant = java.time.Instant;
+var LocalDateTime = java.time.LocalDateTime;
+var ZoneId = java.time.ZoneId;
+ 
+// Date.prototype.getTime
+
+// getTime() method returns the numeric value corresponding to the time
+// for the specified date according to universal time. The value returned
+// by the getTime() method is the number of milliseconds since 1 January 1970 00:00:00 UTC.
+// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime
+ 
+// Java Instant.ofEpochMilli to convert time in milliseconds to Instant object
+// https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html#ofEpochMilli-long-
+ 
+var instant = Instant.ofEpochMilli(d.getTime());
+ 
+// Instant to LocalDateTime using LocalDateTime.ofInstant
+// https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#ofInstant-java.time.Instant-java.time.ZoneId-
+ 
+var ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
+print(ldt);
+ 
+// converting a LocalDateTime to JavaScript Date
+// convert LocalDateTime to Instant first
+// https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#atZone-java.time.ZoneId-
+ 
+var instant = ldt.atZone(ZoneId.systemDefault()).toInstant();
+ 
+// instant to to epoch milliseconds
+// https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html#toEpochMilli--
+// and then to JavaScript Date from time in milliseconds
+// https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date
+
+var d1 = new Date(instant.toEpochMilli());
+print(d1); 
diff --git a/samples/datetime.js b/samples/datetime.js
new file mode 100644
index 0000000..3d5f109
--- /dev/null
+++ b/samples/datetime.js
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// converting b/w JavaScript Date and Java LocalDateTime
+
+// JavaScript Date with current time
+var d = new Date();
+print(d);
+ 
+// Java 8 java.time classes used
+var Instant = java.time.Instant;
+var LocalDateTime = java.time.LocalDateTime;
+var ZoneId = java.time.ZoneId;
+ 
+// Date.prototype.getTime
+
+// getTime() method returns the numeric value corresponding to the time
+// for the specified date according to universal time. The value returned
+// by the getTime() method is the number of milliseconds since 1 January 1970 00:00:00 UTC.
+// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime
+ 
+// Java Instant.ofEpochMilli to convert time in milliseconds to Instant object
+// https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html#ofEpochMilli-long-
+ 
+var instant = Instant.ofEpochMilli(d.getTime());
+ 
+// Instant to LocalDateTime using LocalDateTime.ofInstant
+// https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#ofInstant-java.time.Instant-java.time.ZoneId-
+ 
+var ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
+print(ldt);
+ 
+// converting a LocalDateTime to JavaScript Date
+// convert LocalDateTime to Instant first
+// https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#atZone-java.time.ZoneId-
+ 
+var instant = ldt.atZone(ZoneId.systemDefault()).toInstant();
+ 
+// instant to to epoch milliseconds
+// https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html#toEpochMilli--
+// and then to JavaScript Date from time in milliseconds
+// https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date
+
+var d1 = new Date(instant.toEpochMilli());
+print(d1); 
diff --git a/samples/defaults.js b/samples/defaults.js
new file mode 100644
index 0000000..9347998
--- /dev/null
+++ b/samples/defaults.js
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// print default methods of a Java class
+
+if (arguments.length == 0) {
+   print("Usage: jjs defaults.js -- <java class name>");
+   exit(1);
+}
+
+var jclass = Java.type(arguments[0]).class;
+for each (m in jclass.methods) {
+    // http://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html#isDefault--
+    if (m.default) print(m);
+}
diff --git a/samples/exceptionswallow.js b/samples/exceptionswallow.js
new file mode 100644
index 0000000..82f4e2d
--- /dev/null
+++ b/samples/exceptionswallow.js
@@ -0,0 +1,136 @@
+#// Usage: jjs exceptionswallow.js -- <directory>

+

+/*

+ * Copyright (c) 2015, 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 looks for

+// empty catch blocks ("exception swallow") and reports those.

+

+if (arguments.length == 0) {

+    print("Usage: jjs exceptionswallow.js -- <directory>");

+    exit(1);

+}

+ 

+// Java types used

+var File = Java.type("java.io.File");

+var Files = Java.type("java.nio.file.Files");

+var StringArray = Java.type("java.lang.String[]");

+var ToolProvider = Java.type("javax.tools.ToolProvider");

+var Tree = Java.type("com.sun.source.tree.Tree");

+var EmptyStatementTree = Java.type("com.sun.source.tree.EmptyStatementTree");

+var Trees = Java.type("com.sun.source.util.Trees");

+var TreeScanner = Java.type("com.sun.source.util.TreeScanner");

+

+// printEmptyCatch

+

+function printEmptyCatch() {

+    // 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);

+

+    // SourcePositions object to get positions of AST nodes

+    var sourcePositions = Trees.instance(task).sourcePositions;

+

+    // subclass SimpleTreeVisitor - to print empty catch

+    var EmptyCatchFinder = Java.extend(TreeScanner);

+   

+    function hasOnlyEmptyStats(stats) {

+        var itr = stats.iterator();

+        while (itr.hasNext()) {

+            if (! (itr.next() instanceof EmptyStatementTree)) {

+                return false;

+            }

+        }

+

+        return true;

+    }

+ 

+    var visitor = new EmptyCatchFinder() {

+        // current CompilationUnitTree

+        compUnit: null,

+        // current LineMap (pos -> line, column)

+        lineMap: null,

+        // current compilation unit's file name

+        fileName: null,

+

+        // overrides of TreeScanner methods

+

+        visitCompilationUnit: function(node, p) {

+            // capture info about current Compilation unit

+            this.compUnit = node;

+            this.lineMap = node.lineMap;

+            this.fileName = node.sourceFile.name;

+

+            // Using Java.super API to call super class method here

+            return Java.super(visitor).visitCompilationUnit(node, p);

+        },

+

+        visitCatch: function (node, p) {

+            var stats = node.block.statements;

+            if (stats.empty || hasOnlyEmptyStats(stats)) {

+                // print information on this empty catch

+                var pos = sourcePositions.getStartPosition(this.compUnit, node);

+                var line = this.lineMap.getLineNumber(pos);

+                var col = this.lineMap.getColumnNumber(pos);

+                print("Exception swallow" + " @ " + this.fileName + ":" + line + ":" + col);

+                // print(node);

+            }

+        }

+    }

+ 

+    for each (var cu in task.parse()) {

+        cu.accept(visitor, null);

+    }

+}

+ 

+// for each ".java" file in directory (recursively) and check it!

+function main(dir) {

+    Files.walk(dir.toPath()).

+      forEach(function(p) {

+        var name = p.toFile().absolutePath;

+        if (name.endsWith(".java")) {

+            try {

+                printEmptyCatch(p.toFile().getAbsolutePath());

+            } catch (e) {

+                print(e);

+            }

+        }

+      });

+}

+ 

+main(new File(arguments[0]));

diff --git a/samples/exec.js b/samples/exec.js
new file mode 100644
index 0000000..68581c3
--- /dev/null
+++ b/samples/exec.js
@@ -0,0 +1,50 @@
+# exec script requires -scripting mode
+
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// The $EXEC builtin function can be used to run external commands:
+$EXEC("ls")
+$EXEC("ls -la")
+
+// It can also be given a string to use as stdin:
+$EXEC("cat", "Hello, world!")
+
+// Additional arguments can be passed after the stdin argument, as an array of
+// strings, or a sequence of varargs:
+$EXEC("ls", "" /* no stdin */, "-l", "-a")
+$EXEC("ls", "" /* no stdin */, ["-l", "-a"])
+
+// Output of running external commands is returned from $EXEC:
+print($EXEC("ls"))
+
+// apply on $EXEC
+print($EXEC.apply(this, ["ls"]));
diff --git a/samples/find_max_lines.js b/samples/find_max_lines.js
new file mode 100644
index 0000000..a49d6bd
--- /dev/null
+++ b/samples/find_max_lines.js
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// Find the file with maximum number of lines
+
+var Files = Java.type("java.nio.file.Files");
+var Integer = Java.type("java.lang.Integer");
+var Paths = Java.type("java.nio.file.Paths");
+
+var file = arguments.length == 0? "." : arguments[0];
+var ext = arguments.length > 1? arguments[1] : ".java";
+var path = Paths.get(file);
+
+// return number of lines in given Path (that represents a file)
+function lines(p) {
+    var strm = Files.lines(p);
+    try {
+        return strm.count();
+    } finally {
+        strm.close();
+    }
+}
+
+// walk files, map to file and lines, find the max    
+var obj = Files.find(path, Integer.MAX_VALUE, 
+    function(p, a) !p.toFile().isDirectory() && p.toString().endsWith(ext)).
+map(function(p) ({ path : p, lines: lines(p) })).
+max(function(x, y) x.lines - y.lines).get();
+
+// print path and lines of the max line file
+print(obj.path, obj.lines);
diff --git a/samples/find_nonfinals2.js b/samples/find_nonfinals2.js
index 75fde62..cd00303 100644
--- a/samples/find_nonfinals2.js
+++ b/samples/find_nonfinals2.js
@@ -43,7 +43,6 @@
 // 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");
@@ -106,7 +105,7 @@
 // for each ".java" file in directory (recursively).
 function main(dir) {
     var totalCount = 0;
-    Files.walk(dir.toPath(), FileVisitOption.FOLLOW_LINKS).
+    Files.walk(dir.toPath()).
       forEach(function(p) {
         var name = p.toFile().absolutePath;
         if (name.endsWith(".java")) {
diff --git a/samples/fixed_point.js b/samples/fixed_point.js
new file mode 100644
index 0000000..249384f
--- /dev/null
+++ b/samples/fixed_point.js
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// Simple sample demonstrating "fixed point" computation with Streams
+
+// See also https://mitpress.mit.edu/sicp/chapter1/node21.html#secprocgeneralmethods
+var Stream = Java.type("java.util.stream.Stream");
+
+// generic fixed point procedure
+function fixed_point(f, init_guess) {
+  var tolerance = 0.00001;
+  function close_enough(v1, v2) Math.abs(v1 - v2) < tolerance;
+ 
+  var prev; 
+  return Stream.iterate(init_guess, f)
+      .filter(function(x) {
+          try {
+              return prev == undefined? false : close_enough(prev, x);
+          } finally {
+              prev = x;
+          }
+      })
+      .findFirst()
+      .get();
+}
+
+// solution to x = cos(x)
+print(fixed_point(Math.cos, 1.0))
+
+// solution to x = sin(x) + cos(x)
+print(fixed_point(function(x) Math.sin(x) + Math.cos(x), 1.0));
+
+// square root by Newton's method
+// http://en.wikipedia.org/wiki/Newton's_method
+function sqrt(n)
+  fixed_point(function(x) (x + n/x) / 2, 2.0);
+
+print(sqrt(2))
+print(sqrt(3))
+
+
diff --git a/samples/getclassnpe.js b/samples/getclassnpe.js
new file mode 100644
index 0000000..cc21b72
--- /dev/null
+++ b/samples/getclassnpe.js
@@ -0,0 +1,122 @@
+#// Usage: jjs getclassnpe.js -- <directory>
+
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+/*
+ * java.lang.Object.getClass() is sometimes used to do null check. This
+ * obfuscating Object.getClass() check relies on non-related intrinsic
+ * performance, which is potentially not available everywhere.
+ * See also http://cr.openjdk.java.net/~shade/scratch/NullChecks.java
+ * This nashorn script checks for such uses in your .java files in the
+ * given directory (recursively).
+ */
+
+if (arguments.length == 0) {
+    print("Usage: jjs getclassnpe.js -- <directory>");
+    exit(1);
+}
+
+// Java types used
+var File = Java.type("java.io.File");
+var Files = Java.type("java.nio.file.Files");
+var StringArray = Java.type("java.lang.String[]");
+var ToolProvider = Java.type("javax.tools.ToolProvider");
+var MethodInvocationTree = Java.type("com.sun.source.tree.MethodInvocationTree");
+var TreeScanner = Java.type("com.sun.source.util.TreeScanner");
+
+// parse a specific .java file to check if it uses
+// Object.getClass() for null check.
+function checkGetClassNPE() {
+    // 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 check for obj.getClass(); statements
+    var GetClassNPEChecker = Java.extend(TreeScanner);
+
+    var visitor = new GetClassNPEChecker() {
+        lineMap: null,
+        sourceFile: null,
+
+        // save compilation unit details for reporting
+        visitCompilationUnit: function(node, p) {
+           this.sourceFile = node.sourceFile;
+           this.lineMap = node.lineMap;
+           return Java.super(visitor).visitCompilationUnit(node, p);
+        },
+
+        // look for "foo.getClass();" expression statements
+        visitExpressionStatement: function(node, p) {
+            var expr = node.expression;
+            if (expr instanceof MethodInvocationTree) {
+                var name = String(expr.methodSelect.identifier);
+
+                // will match any "getClass" call with zero arguments!
+                if (name == "getClass" && expr.arguments.size() == 0) {
+                    print(this.sourceFile.getName()
+                     + " @ "
+                     + this.lineMap.getLineNumber(node.pos)
+                     + ":"
+                     + this.lineMap.getColumnNumber(node.pos));
+
+                    print("\t", node);
+                }
+            }
+        }
+    }
+
+    for each (var cu in task.parse()) {
+        cu.accept(visitor, null);
+    }
+}
+
+// for each ".java" file in the directory (recursively)
+function main(dir) {
+    Files.walk(dir.toPath()).
+      forEach(function(p) {
+          var name = p.toFile().absolutePath;
+          if (name.endsWith(".java")) {
+              try {
+                  checkGetClassNPE(p.toFile().getAbsolutePath());
+              } catch (e) {
+                  print(e);
+              }
+          }
+      });
+}
+
+main(new File(arguments[0]));
diff --git a/samples/importstatic.js b/samples/importstatic.js
new file mode 100644
index 0000000..39d9f3c
--- /dev/null
+++ b/samples/importstatic.js
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// Java like "import static class_name.*" for nashorn
+
+function importStatic(clazz) {
+    // make sure the argument is a Java type
+    if (! Java.isType(clazz)) {
+        throw new TypeError(clazz + " is not a Java type");
+    }
+
+    // bind properties of clazz to an object
+    var obj = Object.bindProperties({}, clazz);
+
+    // copy properties to global to "import" those
+    for (var i in obj) {
+        this[i] = obj[i];
+    }
+}
+
+importStatic(java.time.Instant);
+print(now());
+print(ofEpochSecond(1));
+print(parse("2007-12-03T10:15:30.00Z"));
diff --git a/samples/javabind.js b/samples/javabind.js
new file mode 100644
index 0000000..e594efa
--- /dev/null
+++ b/samples/javabind.js
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// bind on a Java method
+
+// #javascript "bind" function
+var bind = Function.prototype.bind;
+
+// Java console object
+var console = java.lang.System.console();
+
+// arguments "this" and prompt string of Console.readLine method are bound
+var readName = bind.call(console.readLine, console, "Your name: ");
+
+// Now call it like a function that takes no arguments!
+print("Hello,", readName());
diff --git a/samples/javaconstructorbind.js b/samples/javaconstructorbind.js
new file mode 100644
index 0000000..68c13f3
--- /dev/null
+++ b/samples/javaconstructorbind.js
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// bind on a Java constructor
+
+// See Function.prototype.bind:
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
+var bind = Function.prototype.bind;
+
+var URL = Java.type("java.net.URL");
+
+// get the constructor that accepts URL, String parameters.
+// constructor signatures are properties of type object.
+var newURL = URL["(URL, String)"];
+
+// bind "context" URL parameter.
+var TwitterURL = bind.call(newURL, null, new URL('https://www.twitter.com'));
+
+// now you can create context relative URLs using the bound constructor
+print(new TwitterURL("sundararajan_a"));
+
+// read the URL content and print (optional part)
+
+var BufferedReader = Java.type("java.io.BufferedReader");
+var InputStreamReader = Java.type("java.io.InputStreamReader");
+
+// function to retrieve text content of the given URL
+function readTextFromURL(url) {
+    var str = '';
+    var u = new URL(url);
+    var reader = new BufferedReader(
+        new InputStreamReader(u.openStream()));
+    try {
+        reader.lines().forEach(function(x) str += x);
+        return str;
+    } finally {
+        reader.close();
+    }
+}
+
+print(readTextFromURL(new TwitterURL("sundararajan_a")));
diff --git a/samples/javafoovars.js b/samples/javafoovars.js
index 037c2bf..31fc5ba 100644
--- a/samples/javafoovars.js
+++ b/samples/javafoovars.js
@@ -42,7 +42,6 @@
 // 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");
@@ -81,7 +80,7 @@
 // for each ".java" file in directory (recursively) count "foo".
 function main(dir) {
     var totalCount = 0;
-    Files.walk(dir.toPath(), FileVisitOption.FOLLOW_LINKS).
+    Files.walk(dir.toPath()).
       forEach(function(p) {
         var name = p.toFile().absolutePath;
         if (name.endsWith(".java")) {
diff --git a/samples/javahelp.js b/samples/javahelp.js
new file mode 100644
index 0000000..b29be01
--- /dev/null
+++ b/samples/javahelp.js
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// script helpers to print meta info on Java instances and classes
+
+// print instance methods info on a Java object or static methods info of a Java class
+function methods(jobj) {
+    if (! Java.isJavaObject(jobj)) {
+        throw new TypeError("not a Java object");
+    }
+
+    var isStatic = Java.isType(jobj);
+    var obj = Object.bindProperties({}, jobj);
+    for each (var i in obj) {
+        if (Java.isJavaMethod(i)) {
+            var str = String(i);
+            var idx = str.indexOf(' ');
+            var overloaded = str.substring(0, idx).endsWith("OverloadedDynamicMethod");
+            var lastIdx = isStatic? str.lastIndexOf('] on') : str.lastIndexOf(']');
+            print(str.substring(idx + 1, lastIdx) + (overloaded? "*" : ""))
+        }
+    }
+}
+
+// print instance field names of a Java object or static field names of a Java class
+function fields(jobj) {
+    if (! Java.isJavaObject(jobj)) {
+        throw new TypeError("not a Java object");
+    }
+
+    var obj = Object.bindProperties({}, jobj);
+    for (var i in obj) {
+        if (! Java.isJavaMethod(obj[i])) {
+            print(i);
+        }
+    }
+}
+
+undefined;
diff --git a/samples/jd.js b/samples/jd.js
new file mode 100644
index 0000000..7b7bc96
--- /dev/null
+++ b/samples/jd.js
@@ -0,0 +1,94 @@
+#// Usage: jjs -cp <asmtools.jar> jd.js -- <classname> [jdis|jdec]
+
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// javap-like disassembler/decoder tool that disassembles/decodes 
+// java classes but with OpenJDK AsmTools disassembler/decoder syntax.
+// You need to build asmtool.jar from OpenJDK codetools project
+// specify it with -cp option.
+
+// See also https://wiki.openjdk.java.net/display/CodeTools/AsmTools
+
+function usage() {
+    print("Usage: jjs -cp <asmtools.jar> jd.js -- <classname> [jdis|jdec]");
+    exit(1);
+}
+
+if (arguments.length == 0) {
+    usage();
+}
+
+// argument handling
+// convert to internal class name
+var className = arguments[0].replaceAll('\\.', '/');
+var tool;
+if (arguments.length > 1) {
+    tool = arguments[1];
+    switch (tool) {
+        case 'jdis':
+        case 'jdec':
+            break;
+        default:
+            usage();
+    }
+} else {
+    tool = "jdis"; // default tool
+}
+
+// Java classes used
+var AsmTools = Java.type("org.openjdk.asmtools.Main");
+var Files = Java.type("java.nio.file.Files");
+var StandardCopyOption = Java.type("java.nio.file.StandardCopyOption");
+
+// retrive input stream for .class bytes
+var cl = AsmTools.class.classLoader;
+var res = cl.getResource(className + ".class");
+
+if (res) {
+    var is = res.openStream();
+    var tmpPath;
+    try {
+        // copy the content of the .class to a temp file
+        tmpPath = Files.createTempFile("asmtools-", ".class");
+        // mark as delete-on-exit
+        tmpPath.toFile().deleteOnExit();
+        Files.copy(is, tmpPath, [ StandardCopyOption.REPLACE_EXISTING ]);
+    } finally {
+        is.close();
+    } 
+
+    // invoke asmtools Main
+    AsmTools.main([ tool, tmpPath.toString() ]);
+} else {
+    print("no such class: " + arguments[0]);
+    exit(1);
+}
diff --git a/samples/mapwith.js b/samples/mapwith.js
new file mode 100644
index 0000000..70672d4
--- /dev/null
+++ b/samples/mapwith.js
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// Using a Java map with Javascript "with" statement
+
+var map = new java.util.HashMap();
+map.put("foo", 34);
+map.put("bar", "hello");
+
+var obj = {
+    __noSuchProperty__: function(name) {
+        return map.get(name);
+    }
+};
+
+with(obj) {
+   print(foo);
+   print(bar);
+}
diff --git a/samples/mothers_day.js b/samples/mothers_day.js
new file mode 100644
index 0000000..e232633
--- /dev/null
+++ b/samples/mothers_day.js
@@ -0,0 +1,56 @@
+# compute Mothers day of the given the year
+
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// print "Mother's day" of the given year using Java Time API
+
+if (arguments.length == 0) {
+    print("Usage: jjs mothers_day.js -- year");
+    exit(1);
+}
+
+// java classes used
+var DayOfWeek = java.time.DayOfWeek;
+var LocalDate = java.time.LocalDate;
+var TemporalAdjusters = java.time.temporal.TemporalAdjusters;
+
+var year = parseInt(arguments[0]);
+
+// See: https://en.wikipedia.org/?title=Mother%27s_Day
+// We need second Sunday of May. Make April 30 of the given
+// year adjust and adjust to next Sunday from there twice. To adjust a Date
+// we use a common TemporalAdjuster provided in JDK8.
+// https://docs.oracle.com/javase/8/docs/api/java/time/temporal/TemporalAdjusters.html
+
+print(LocalDate.of(year, 4, 30).
+    with(TemporalAdjusters.next(DayOfWeek.SUNDAY)).
+    with(TemporalAdjusters.next(DayOfWeek.SUNDAY)));
diff --git a/samples/passwordgen.js b/samples/passwordgen.js
new file mode 100644
index 0000000..82c4055
--- /dev/null
+++ b/samples/passwordgen.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// Simple password generator using SecureRandom + stream API
+
+// accept optional password length from command line
+var len = arguments.length? parseInt(arguments[0]) : 8;
+
+// Java types used
+var Collectors = Java.type("java.util.stream.Collectors");
+var SecureRandom = Java.type("java.security.SecureRandom");
+
+// allowed password chars
+var chars =
+ "!@#$%ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+// generated and print password
+print(new SecureRandom().
+    ints(len, 0, chars.length).
+    mapToObj(function(i) chars[i]).
+    collect(Collectors.joining("")));
diff --git a/samples/print_symlinks.js b/samples/print_symlinks.js
new file mode 100644
index 0000000..410b843
--- /dev/null
+++ b/samples/print_symlinks.js
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// Print all symbolic links in user's home directory
+
+// JavaImporter and "with" to simulate "import" statements in Java.
+// See https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions
+
+with (new JavaImporter(java.nio.file, java.lang)) {
+
+  var userDir = System.getProperty("user.dir")
+  var home = FileSystems.default.getPath(userDir);
+
+  // JS functions can be passed where Java lambdas are required.
+  // Also, using "Expression closure" extension here.
+  // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Expression_Closures
+
+  Files.walk(home).
+    filter(function(p) Files.isSymbolicLink(p)).
+    forEach(function(p)
+      print(p, '->', Files.readSymbolicLink(p)));
+}
diff --git a/samples/resourcetrysuggester.js b/samples/resourcetrysuggester.js
new file mode 100644
index 0000000..d21276c
--- /dev/null
+++ b/samples/resourcetrysuggester.js
@@ -0,0 +1,156 @@
+#// Usage: jjs resourcetrysuggester.js -- <directory>

+

+/*

+ * Copyright (c) 2015, 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 looks for

+// finally clauses with "close" call and suggests "resource try"!

+

+if (arguments.length == 0) {

+    print("Usage: jjs resourcetrysuggester.js -- <directory>");

+    exit(1);

+}

+ 

+// Java types used

+var ExpressionStatementTree = Java.type("com.sun.source.tree.ExpressionStatementTree");

+var File = Java.type("java.io.File");

+var Files = Java.type("java.nio.file.Files");

+var MemberSelectTree = Java.type("com.sun.source.tree.MemberSelectTree");

+var MethodInvocationTree = Java.type("com.sun.source.tree.MethodInvocationTree");

+var StringArray = Java.type("java.lang.String[]");

+var ToolProvider = Java.type("javax.tools.ToolProvider");

+var Tree = Java.type("com.sun.source.tree.Tree");

+var Trees = Java.type("com.sun.source.util.Trees");

+var TreeScanner = Java.type("com.sun.source.util.TreeScanner");

+

+// resourceTrySuggestions

+

+function resourceTrySuggestions() {

+    // 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);

+

+    // SourcePositions object to get positions of AST nodes

+    var sourcePositions = Trees.instance(task).sourcePositions;

+

+    // subclass SimpleTreeVisitor - to print resource try suggestions

+    var ResourceTrySuggester = Java.extend(TreeScanner);

+   

+    function hasOnlyEmptyStats(stats) {

+        var itr = stats.iterator();

+        while (itr.hasNext()) {

+            if (! (itr.next() instanceof EmptyStatementTree)) {

+                return false;

+            }

+        }

+

+        return true;

+    }

+

+    // does the given statement list has an expression statement which

+    // calls "close" method (don't worry about types - just crude one will do)

+    function hasCloseCall(stats) {

+        var itr = stats.iterator();

+        while (itr.hasNext()) {

+            var stat = itr.next();

+            if (stat instanceof ExpressionStatementTree) {

+                var expr = stat.expression;

+                if (expr instanceof MethodInvocationTree) {

+                    var method = expr.methodSelect;

+                    if (method instanceof MemberSelectTree) {

+                        return method.identifier.toString().equals("close");

+                    }

+                }

+            }

+        }

+        return false;

+    }

+ 

+    var visitor = new ResourceTrySuggester() {

+        // current CompilationUnitTree

+        compUnit: null,

+        // current LineMap (pos -> line, column)

+        lineMap: null,

+        // current compilation unit's file name

+        fileName: null,

+

+        // overrides of TreeScanner methods

+

+        visitCompilationUnit: function(node, p) {

+            // capture info about current Compilation unit

+            this.compUnit = node;

+            this.lineMap = node.lineMap;

+            this.fileName = node.sourceFile.name;

+

+            // Using Java.super API to call super class method here

+            return Java.super(visitor).visitCompilationUnit(node, p);

+        },

+

+        visitTry: function (node, p) {

+            var finallyBlk = node.finallyBlock;

+            if (finallyBlk != null && hasCloseCall(finallyBlk.statements)) {

+                var pos = sourcePositions.getStartPosition(this.compUnit, node);

+                var line = this.lineMap.getLineNumber(pos);

+                var col = this.lineMap.getColumnNumber(pos);

+                print("Consider resource try statement " + " @ " + this.fileName + ":" + line + ":" + col);

+                // print(node);

+            }

+        }

+    }

+ 

+    for each (var cu in task.parse()) {

+        cu.accept(visitor, null);

+    }

+}

+ 

+// for each ".java" file in directory (recursively) and check it!

+function main(dir) {

+    Files.walk(dir.toPath()).

+      forEach(function(p) {

+        var name = p.toFile().absolutePath;

+        if (name.endsWith(".java")) {

+            try {

+                resourceTrySuggestions(p.toFile().getAbsolutePath());

+            } catch (e) {

+                print(e);

+            }

+        }

+      });

+}

+ 

+main(new File(arguments[0]));

diff --git a/samples/secondssince.js b/samples/secondssince.js
new file mode 100644
index 0000000..55067aa
--- /dev/null
+++ b/samples/secondssince.js
@@ -0,0 +1,43 @@
+# usage: jjs secondssince.js
+
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// Number of seconds elapsed since the specified Instance #nashorn #javascript #java
+// Input date and time in ISO 8601 format
+// Example: 2001-01-01T00:00:00Z for 1 Jan 2001, 0 GMT
+
+var Instant = java.time.Instant;
+var ChronoUnit = java.time.temporal.ChronoUnit;
+print("Enter date time:");
+var sec = Instant.parse(readLine()).
+      until(Instant.now(), ChronoUnit.SECONDS);
+print(sec);
diff --git a/samples/showenv.js b/samples/showenv.js
new file mode 100644
index 0000000..6e39cb9
--- /dev/null
+++ b/samples/showenv.js
@@ -0,0 +1,82 @@
+#// Usage: jjs -fx showenv.js
+
+/*
+ * Copyright (c) 2015, 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 (!$OPTIONS._fx) {
+    print("Usage: jjs -fx showenv.js");
+    exit(1);
+}
+
+// This script displays environment entries as a HTML table.
+// Demonstrates heredoc to generate HTML content and display
+// using JavaFX WebView.
+
+// JavaFX classes used
+var Scene     = Java.type("javafx.scene.Scene");
+var WebView   = Java.type("javafx.scene.web.WebView");
+
+// JavaFX start method
+function start(stage) {
+    start.title = "Your Environment";
+    var wv = new WebView();
+    var envrows = "";
+    for (var i in $ENV) {
+        envrows += <<TBL
+<tr>
+<td>
+${i}
+</td>
+<td>
+${$ENV[i]}
+</td>
+</tr>
+TBL
+    }
+
+    wv.engine.loadContent(<<EOF
+<html>
+<head>
+<title>
+Your Environment
+</title>
+</head>
+<body>
+<h1>Your Environment</h1>
+<table border="1">
+${envrows}
+</table>
+</body>
+</html>
+EOF, "text/html");
+    stage.scene = new Scene(wv, 750, 500);
+    stage.show();
+}
diff --git a/samples/showsysprops.js b/samples/showsysprops.js
new file mode 100644
index 0000000..856878b
--- /dev/null
+++ b/samples/showsysprops.js
@@ -0,0 +1,84 @@
+#// Usage: jjs -fx showsysprops.js
+
+/*
+ * Copyright (c) 2015, 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 (!$OPTIONS._fx) {
+    print("Usage: jjs -fx showsysprops.js");
+    exit(1);
+}
+
+// This script displays System properties as a HTML table.
+// Demonstrates heredoc to generate HTML content and display
+// using JavaFX WebView.
+
+// JavaFX, Java classes used
+var Scene     = Java.type("javafx.scene.Scene");
+var System    = Java.type("java.lang.System");
+var WebView   = Java.type("javafx.scene.web.WebView");
+
+// JavaFX start method
+function start(stage) {
+    start.title = "Your System Properties";
+    var wv = new WebView();
+    var sysproprows = "";
+    var sysprops = System.properties;
+    for (var i in sysprops) {
+        sysproprows += <<TBL
+<tr>
+<td>
+${i}
+</td>
+<td>
+${sysprops[i]}
+</td>
+</tr>
+TBL
+    }
+
+    wv.engine.loadContent(<<EOF
+<html>
+<head>
+<title>
+Your System Properties
+</title>
+</head>
+<body>
+<h1>Your System Properties</h1>
+<table border="1">
+${sysproprows}
+</table>
+</body>
+</html>
+EOF, "text/html");
+    stage.scene = new Scene(wv, 750, 500);
+    stage.show();
+}
diff --git a/samples/sort_by_java8.js b/samples/sort_by_java8.js
new file mode 100644
index 0000000..21eba69
--- /dev/null
+++ b/samples/sort_by_java8.js
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// Simple sorting with Java8 APIs
+
+// Separation key-extraction from key ordering
+
+// Simple demo for Comparator.comparing
+// http://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html#comparing-java.util.function.Function-
+
+// data to be sorted
+var cards = [
+   { name: "hello", email: "foo@hello.com" },
+   { name: "world", email: "bar@world.com" },
+   { name: "see", email: "see@dontsee.com" },
+];
+
+var Collections = java.util.Collections;
+var Comparator = java.util.Comparator;
+
+// sort records name in reverse order of names
+Collections.sort(cards,
+  Comparator.comparing(function(a) a.name).reversed());
+
+print(JSON.stringify(cards))
+
+// sort records by email
+Collections.sort(cards,
+  Comparator.comparing(function(a) a.email));
+
+print(JSON.stringify(cards))
diff --git a/samples/this_for_eval.js b/samples/this_for_eval.js
new file mode 100644
index 0000000..58f584a
--- /dev/null
+++ b/samples/this_for_eval.js
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// how to pass arbitrary "this" object for eval'ed script?
+
+var obj = { foo: 44 };
+
+// the following won't work. eval.apply is indirect eval call
+// and so 'this' will be global object always! So, this
+// line will print 'undefined'
+eval.apply(obj, [ " print(this.foo)" ]);
+
+obj.myEval = eval;
+
+// still won't work - still indirect 'eval' call!
+// still undefined is printed!
+obj.myEval("print(this.foo)");
+
+function func(code) {
+    eval(code);
+}
+
+// eval called inside func and so get's func's "this" as it's "this"!
+// So, 44 is printed
+
+func.apply(obj, [ "print(this.foo)" ]);
diff --git a/samples/time_color.fx b/samples/time_color.fx
new file mode 100644
index 0000000..f4b1155
--- /dev/null
+++ b/samples/time_color.fx
@@ -0,0 +1,89 @@
+#// Usage: jjs -fx time_color.js [-- true/false]
+
+/*
+ * 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.
+ */
+
+// A simple javafx program that changes background color
+// of scene based on current time value (once per sec).
+// inspired by http://whatcolourisit.scn9a.org/
+
+if (!$OPTIONS._fx) {
+    print("Usage: jjs -fx time_color.js");
+    print("       jjs -fx time_color.js -- true");
+    exit(1);
+}
+
+// JavaFX classes used
+var Color = Java.type("javafx.scene.paint.Color");
+var Group = Java.type("javafx.scene.Group");
+var Label = Java.type("javafx.scene.control.Label");
+var Platform = Java.type("javafx.application.Platform");
+var Scene = Java.type("javafx.scene.Scene");
+var Timer = Java.type("java.util.Timer");
+
+// execute function periodically once per given time in millisec
+function setInterval(func, ms) {
+    // New timer, run as daemon so the application can quit
+    var timer = new Timer("setInterval", true);
+    timer.schedule(function() Platform.runLater(func), ms, ms);	
+    return timer;
+}
+
+// do you want to flip hour/min/sec for RGB?
+var flip = arguments.length > 0? "true".equals(arguments[0]) : false;
+
+// JavaFX start method
+function start(stage) {
+    start.title = "Time Color";
+    var root = new Group();
+    var label = new Label("time");
+    label.textFill = Color.WHITE;
+    root.children.add(label); 
+    stage.scene = new Scene(root, 700, 500);
+
+    setInterval(function() {
+        var d = new Date();
+        var hours = d.getHours();
+	var mins = d.getMinutes();
+	var secs = d.getSeconds();
+
+        if (hours < 10) hours = "0" + hours;
+        if (mins < 10) mins = "0" + mins;
+        if (secs < 10) secs = "0" + secs;
+
+	var hex = flip?
+            "#" + secs + mins + hours : "#" + hours + mins + secs;
+        label.text = "Color: " + hex;
+        stage.scene.fill = Color.web(hex);
+    }, 1000);
+
+    stage.show();
+}
diff --git a/samples/undefined_call.js b/samples/undefined_call.js
new file mode 100644
index 0000000..b82531a
--- /dev/null
+++ b/samples/undefined_call.js
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+// Nashorn extension: __noSuchMethod__
+// See also: https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions#Nashornextensions-__noSuchMethod__
+ 
+Object.prototype.__noSuchMethod__ = function(name) {
+    print(name + " function is not defined in " + this);
+ 
+    // Nashorn extension: stack property
+    // gives stack trace as a string
+    print(new Error().stack);
+}
+ 
+function func(obj) {
+    obj.foo();
+}
+ 
+func({});
+func(this); 
diff --git a/samples/unzip.js b/samples/unzip.js
new file mode 100644
index 0000000..df2a796
--- /dev/null
+++ b/samples/unzip.js
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+/*
+ * Simple unzip tool using #nashorn and #java
+ * zip fs file system interface.
+ */
+ 
+if (arguments.length == 0) {
+    print("Usage: jjs zipfs.js -- <.zip/.jar file> [out dir]");
+    exit(1);
+}
+ 
+var File = Java.type("java.io.File");
+// output directory where zip is extracted
+var outDir = arguments[1];
+if (!outDir) {
+    outDir = ".";
+} else {
+    if (! new File(outDir).isDirectory()) {
+        print(outDir + " directory does not exist!");
+        exit(1);
+    }
+}
+ 
+var Files = Java.type("java.nio.file.Files");
+var FileSystems = Java.type("java.nio.file.FileSystems");
+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];
+ 
+// walk root and handle each Path
+Files.walk(root).forEach(
+    function(p) {
+        var outPath = outDir +
+            p.toString().replace('/', File.separatorChar);
+        print(outPath);
+        if (Files.isDirectory(p)) {
+            // create directories as needed
+            new File(outPath).mkdirs();
+        } else {
+            // copy a 'file' resource
+            Files.copy(p, new File(outPath).toPath());
+        }
+    }
+);
+ 
+// done
+fs.close(); 
diff --git a/samples/zipfs.js b/samples/zipfs.js
index ecb6f61..fba5f15 100644
--- a/samples/zipfs.js
+++ b/samples/zipfs.js
@@ -36,13 +36,12 @@
 
 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(
+Files.walk(root).forEach(
    function(p) (print(p), print(Files.readAttributes(p, "zip:*")))
 )
 fs.close()
diff --git a/src/jdk/internal/dynalink/DynamicLinker.java b/src/jdk/internal/dynalink/DynamicLinker.java
index e7e58d2..7839467 100644
--- a/src/jdk/internal/dynalink/DynamicLinker.java
+++ b/src/jdk/internal/dynalink/DynamicLinker.java
@@ -88,6 +88,7 @@
 import java.lang.invoke.MethodType;
 import java.lang.invoke.MutableCallSite;
 import java.util.List;
+import java.util.Objects;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.GuardingDynamicLinker;
 import jdk.internal.dynalink.linker.LinkRequest;
@@ -98,10 +99,12 @@
 import jdk.internal.dynalink.support.RuntimeContextLinkRequestImpl;
 
 /**
- * The linker for {@link RelinkableCallSite} objects. Users of it (scripting frameworks and language runtimes) have to
- * create a linker using the {@link DynamicLinkerFactory} and invoke its link method from the invokedynamic bootstrap
- * methods to set the target of all the call sites in the code they generate. Usual usage would be to create one class
- * per language runtime to contain one linker instance as:
+ * The linker for {@link RelinkableCallSite} objects. Users of it (scripting
+ * frameworks and language runtimes) have to create a linker using the
+ * {@link DynamicLinkerFactory} and invoke its link method from the invokedynamic
+ * bootstrap methods to set the target of all the call sites in the code they
+ * generate. Usual usage would be to create one class per language runtime to
+ * contain one linker instance as:
  *
  * <pre>
  * class MyLanguageRuntime {
@@ -114,7 +117,7 @@
  *         return factory.createLinker();
  *     }
  *
- *     public static CallSite bootstrap(MethodHandles.Lookup caller, String name, MethodType type) {
+ *     public static CallSite bootstrap(MethodHandles.Lookup lookup, String name, MethodType type) {
  *         return dynamicLinker.link(new MonomorphicCallSite(CallSiteDescriptorFactory.create(lookup, name, type)));
  *     }
  * }
@@ -122,19 +125,27 @@
  *
  * Note how there are three components you will need to provide here:
  * <ul>
- * <li>You're expected to provide a {@link GuardingDynamicLinker} for your own language. If your runtime doesn't
- * have its own language and/or object model (i.e. it's a generic scripting shell), you don't need to implement a
- * dynamic linker; you would simply not invoke the {@code setPrioritizedLinker} method on the factory, or even better,
- * simply use {@link DefaultBootstrapper}.</li>
- * <li>The performance of the programs can depend on your choice of the class to represent call sites. The above
- * example used {@link MonomorphicCallSite}, but you might want to use {@link ChainedCallSite} instead. You'll need to
- * experiment and decide what fits your language runtime the best. You can subclass either of these or roll your own if
- * you need to.</li>
- * <li>You also need to provide {@link CallSiteDescriptor}s to your call sites. They are immutable objects that contain
- * all the information about the call site: the class performing the lookups, the name of the method being invoked, and
- * the method signature. The library has a default {@link CallSiteDescriptorFactory} for descriptors that you can use,
- * or you can create your own descriptor classes, especially if you need to add further information (values passed in
+ *
+ * <li>You're expected to provide a {@link GuardingDynamicLinker} for your own
+ * language. If your runtime doesn't have its own language and/or object model
+ * (i.e., it's a generic scripting shell), you don't need to implement a dynamic
+ * linker; you would simply not invoke the {@code setPrioritizedLinker} method
+ * on the factory, or even better, simply use {@link DefaultBootstrapper}.</li>
+ *
+ * <li>The performance of the programs can depend on your choice of the class to
+ * represent call sites. The above example used {@link MonomorphicCallSite}, but
+ * you might want to use {@link ChainedCallSite} instead. You'll need to
+ * experiment and decide what fits your language runtime the best. You can
+ * subclass either of these or roll your own if you need to.</li>
+ *
+ * <li>You also need to provide {@link CallSiteDescriptor}s to your call sites.
+ * They are immutable objects that contain all the information about the call
+ * site: the class performing the lookups, the name of the method being invoked,
+ * and the method signature. The library has a default {@link CallSiteDescriptorFactory}
+ * for descriptors that you can use, or you can create your own descriptor
+ * classes, especially if you need to add further information (values passed in
  * additional parameters to the bootstrap method) to them.</li>
+ *
  * </ul>
  *
  * @author Attila Szegedi
@@ -175,11 +186,15 @@
     }
 
     /**
-     * Links an invokedynamic call site. It will install a method handle into the call site that invokes the relinking
-     * mechanism of this linker. Next time the call site is invoked, it will be linked for the actual arguments it was
-     * invoked with.
+     * Links an invokedynamic call site. It will install a method handle into
+     * the call site that invokes the relinking mechanism of this linker. Next
+     * time the call site is invoked, it will be linked for the actual arguments
+     * it was invoked with.
      *
+     * @param <T> the particular subclass of {@link RelinkableCallSite} for
+     *        which to create a link.
      * @param callSite the call site to link.
+     *
      * @return the callSite, for easy call chaining.
      */
     public <T extends RelinkableCallSite> T link(final T callSite) {
@@ -188,10 +203,13 @@
     }
 
     /**
-     * Returns the object representing the lower level linker services of this class that are normally exposed to
-     * individual language-specific linkers. While as a user of this class you normally only care about the
-     * {@link #link(RelinkableCallSite)} method, in certain circumstances you might want to use the lower level services
-     * directly; either to lookup specific method handles, to access the type converters, and so on.
+     * Returns the object representing the lower level linker services of this
+     * class that are normally exposed to individual language-specific linkers.
+     * While as a user of this class you normally only care about the
+     * {@link #link(RelinkableCallSite)} method, in certain circumstances you
+     * might want to use the lower level services directly; either to lookup
+     * specific method handles, to access the type converters, and so on.
+     *
      * @return the object representing the linker services of this class.
      */
     public LinkerServices getLinkerServices() {
@@ -217,7 +235,9 @@
      *
      * @param callSite the call site itself
      * @param arguments arguments to the invocation
+     *
      * @return return the method handle for the invocation
+     *
      * @throws Exception rethrows any exception thrown by the linkers
      */
     @SuppressWarnings("unused")
@@ -252,7 +272,7 @@
         // 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
+        Objects.requireNonNull(guardedInvocation);
 
         int newRelinkCount = relinkCount;
         // Note that the short-circuited "&&" evaluation below ensures we'll increment the relinkCount until
@@ -271,11 +291,15 @@
     }
 
     /**
-     * Returns a stack trace element describing the location of the call site currently being linked on the current
-     * thread. The operation internally creates a Throwable object and inspects its stack trace, so it's potentially
-     * expensive. The recommended usage for it is in writing diagnostics code.
-     * @return a stack trace element describing the location of the call site currently being linked, or null if it is
-     * not invoked while a call site is being linked.
+     * Returns a stack trace element describing the location of the call site
+     * currently being linked on the current thread. The operation internally
+     * creates a Throwable object and inspects its stack trace, so it's
+     * potentially expensive. The recommended usage for it is in writing
+     * diagnostics code.
+     *
+     * @return a stack trace element describing the location of the call site
+     *         currently being linked, or null if it is not invoked while a call
+     *         site is being linked.
      */
     public static StackTraceElement getLinkedCallSiteLocation() {
         final StackTraceElement[] trace = new Throwable().getStackTrace();
@@ -289,8 +313,10 @@
     }
 
     /**
-     * Deprecated because of not precise name.
+     * Deprecated because of imprecise name.
+     *
      * @deprecated Use {@link #getLinkedCallSiteLocation()} instead.
+     *
      * @return see non-deprecated method
      */
     @Deprecated
@@ -299,20 +325,26 @@
     }
 
     /**
-     * Returns true if the frame represents {@code MethodHandleNatives.linkCallSite()}, the frame immediately on top of
-     * the call site frame when the call site is being linked for the first time.
+     * Returns {@code true} if the frame represents {@code MethodHandleNatives.linkCallSite()},
+     * the frame immediately on top of the call site frame when the call site is
+     * being linked for the first time.
+     *
      * @param frame the frame
-     * @return true if this frame represents {@code MethodHandleNatives.linkCallSite()}
+     *
+     * @return {@code true} if this frame represents {@code MethodHandleNatives.linkCallSite()}.
      */
     private static boolean isInitialLinkFrame(final StackTraceElement frame) {
         return testFrame(frame, INITIAL_LINK_METHOD_NAME, INITIAL_LINK_CLASS_NAME);
     }
 
     /**
-     * Returns true if the frame represents {@code DynamicLinker.relink()}, the frame immediately on top of the call
-     * site frame when the call site is being relinked (linked for second and subsequent times).
+     * Returns {@code true} if the frame represents {@code DynamicLinker.relink()},
+     * the frame immediately on top of the call site frame when the call site is
+     * being relinked (linked for second and subsequent times).
+     *
      * @param frame the frame
-     * @return true if this frame represents {@code DynamicLinker.relink()}
+     *
+     * @return {@code true} if this frame represents {@code DynamicLinker.relink()}.
      */
     private static boolean isRelinkFrame(final StackTraceElement frame) {
         return testFrame(frame, RELINK_METHOD_NAME, CLASS_NAME);
diff --git a/src/jdk/internal/dynalink/DynamicLinkerFactory.java b/src/jdk/internal/dynalink/DynamicLinkerFactory.java
index 2f4e5f3..5a6ce1b 100644
--- a/src/jdk/internal/dynalink/DynamicLinkerFactory.java
+++ b/src/jdk/internal/dynalink/DynamicLinkerFactory.java
@@ -97,6 +97,8 @@
 import jdk.internal.dynalink.linker.GuardingDynamicLinker;
 import jdk.internal.dynalink.linker.GuardingTypeConverterFactory;
 import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.internal.dynalink.linker.LinkerServices;
+import jdk.internal.dynalink.linker.MethodHandleTransformer;
 import jdk.internal.dynalink.linker.MethodTypeConversionStrategy;
 import jdk.internal.dynalink.support.AutoDiscovery;
 import jdk.internal.dynalink.support.BottomGuardingDynamicLinker;
@@ -132,6 +134,7 @@
     private int unstableRelinkThreshold = DEFAULT_UNSTABLE_RELINK_THRESHOLD;
     private GuardedInvocationFilter prelinkFilter;
     private MethodTypeConversionStrategy autoConversionStrategy;
+    private MethodHandleTransformer internalObjectsFilter;
 
     /**
      * Sets the class loader for automatic discovery of available linkers. If not set explicitly, then the thread
@@ -284,6 +287,15 @@
     }
 
     /**
+     * Sets a method handle transformer that is supposed to act as the implementation of this linker factory's linkers'
+     * services {@link LinkerServices#filterInternalObjects(java.lang.invoke.MethodHandle)} method.
+     * @param internalObjectsFilter a method handle transformer filtering out internal objects, or null.
+     */
+    public void setInternalObjectsFilter(final MethodHandleTransformer internalObjectsFilter) {
+        this.internalObjectsFilter = internalObjectsFilter;
+    }
+
+    /**
      * Creates a new dynamic linker consisting of all the prioritized, autodiscovered, and fallback linkers as well as
      * the pre-link filter.
      *
@@ -350,8 +362,8 @@
         }
 
         return new DynamicLinker(new LinkerServicesImpl(new TypeConverterFactory(typeConverters,
-                autoConversionStrategy), composite), prelinkFilter, runtimeContextArgCount, syncOnRelink,
-                unstableRelinkThreshold);
+                autoConversionStrategy), composite, internalObjectsFilter), prelinkFilter, runtimeContextArgCount,
+                syncOnRelink, unstableRelinkThreshold);
     }
 
     private static ClassLoader getThreadContextClassLoader() {
diff --git a/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java b/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java
index cf1b11d..f8b13ad 100644
--- a/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java
+++ b/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java
@@ -570,7 +570,7 @@
     private static final MethodHandle CONSTANT_NULL_DROP_ANNOTATED_METHOD = MethodHandles.dropArguments(
             MethodHandles.constant(Object.class, null), 0, AnnotatedDynamicMethod.class);
     private static final MethodHandle GET_ANNOTATED_METHOD = privateLookup.findVirtual(AnnotatedDynamicMethod.class,
-            "getTarget", MethodType.methodType(MethodHandle.class, MethodHandles.Lookup.class));
+            "getTarget", MethodType.methodType(MethodHandle.class, MethodHandles.Lookup.class, LinkerServices.class));
     private static final MethodHandle GETTER_INVOKER = MethodHandles.invoker(MethodType.methodType(Object.class, Object.class));
 
     private GuardedInvocationComponent getPropertyGetter(final CallSiteDescriptor callSiteDescriptor,
@@ -593,7 +593,7 @@
                 final MethodHandle typedGetter = linkerServices.asType(getPropertyGetterHandle, type.changeReturnType(
                         AnnotatedDynamicMethod.class));
                 final MethodHandle callSiteBoundMethodGetter = MethodHandles.insertArguments(
-                        GET_ANNOTATED_METHOD, 1, callSiteDescriptor.getLookup());
+                        GET_ANNOTATED_METHOD, 1, callSiteDescriptor.getLookup(), linkerServices);
                 final MethodHandle callSiteBoundInvoker = MethodHandles.filterArguments(GETTER_INVOKER, 0,
                         callSiteBoundMethodGetter);
                 // Object(AnnotatedDynamicMethod, Object)->Object(AnnotatedDynamicMethod, T0)
@@ -782,7 +782,7 @@
      */
     @SuppressWarnings("unused")
     private Object getPropertyGetterHandle(final Object id) {
-        return propertyGetters.get(id);
+        return propertyGetters.get(String.valueOf(id));
     }
 
     // Type is MethodHandle(BeanLinker, MethodType, LinkerServices, Object, String, Object), of which the two "Object"
@@ -873,8 +873,8 @@
         }
 
         @SuppressWarnings("unused")
-        MethodHandle getTarget(final MethodHandles.Lookup lookup) {
-            final MethodHandle inv = method.getTarget(lookup);
+        MethodHandle getTarget(final MethodHandles.Lookup lookup, final LinkerServices linkerServices) {
+            final MethodHandle inv = linkerServices.filterInternalObjects(method.getTarget(lookup));
             assert inv != null;
             return inv;
         }
diff --git a/src/jdk/internal/dynalink/beans/BeanLinker.java b/src/jdk/internal/dynalink/beans/BeanLinker.java
index f7f0c94..a7dad71 100644
--- a/src/jdk/internal/dynalink/beans/BeanLinker.java
+++ b/src/jdk/internal/dynalink/beans/BeanLinker.java
@@ -165,6 +165,10 @@
     private static MethodHandle LIST_GUARD = Guards.getInstanceOfGuard(List.class);
     private static MethodHandle MAP_GUARD = Guards.getInstanceOfGuard(Map.class);
 
+    private enum CollectionType {
+        ARRAY, LIST, MAP
+    };
+
     private GuardedInvocationComponent getElementGetter(final CallSiteDescriptor callSiteDescriptor,
             final LinkerServices linkerServices, final List<String> operations) throws Exception {
         final MethodType callSiteType = callSiteDescriptor.getMethodType();
@@ -178,27 +182,27 @@
         // Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers
         // in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices.
         final GuardedInvocationComponent gic;
-        final boolean isMap;
+        final CollectionType collectionType;
         if(declaredType.isArray()) {
-            gic = new GuardedInvocationComponent(MethodHandles.arrayElementGetter(declaredType));
-            isMap = false;
+            gic = createInternalFilteredGuardedInvocationComponent(MethodHandles.arrayElementGetter(declaredType), linkerServices);
+            collectionType = CollectionType.ARRAY;
         } else if(List.class.isAssignableFrom(declaredType)) {
-            gic = new GuardedInvocationComponent(GET_LIST_ELEMENT);
-            isMap = false;
+            gic = createInternalFilteredGuardedInvocationComponent(GET_LIST_ELEMENT, linkerServices);
+            collectionType = CollectionType.LIST;
         } else if(Map.class.isAssignableFrom(declaredType)) {
-            gic = new GuardedInvocationComponent(GET_MAP_ELEMENT);
-            isMap = true;
+            gic = createInternalFilteredGuardedInvocationComponent(GET_MAP_ELEMENT, linkerServices);
+            collectionType = CollectionType.MAP;
         } else if(clazz.isArray()) {
-            gic = getClassGuardedInvocationComponent(MethodHandles.arrayElementGetter(clazz), callSiteType);
-            isMap = false;
+            gic = getClassGuardedInvocationComponent(linkerServices.filterInternalObjects(MethodHandles.arrayElementGetter(clazz)), callSiteType);
+            collectionType = CollectionType.ARRAY;
         } else if(List.class.isAssignableFrom(clazz)) {
-            gic = new GuardedInvocationComponent(GET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class,
-                    ValidationType.INSTANCE_OF);
-            isMap = false;
+            gic = createInternalFilteredGuardedInvocationComponent(GET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class, ValidationType.INSTANCE_OF,
+                    linkerServices);
+            collectionType = CollectionType.LIST;
         } else if(Map.class.isAssignableFrom(clazz)) {
-            gic = new GuardedInvocationComponent(GET_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType), Map.class,
-                    ValidationType.INSTANCE_OF);
-            isMap = true;
+            gic = createInternalFilteredGuardedInvocationComponent(GET_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType), Map.class, ValidationType.INSTANCE_OF,
+                    linkerServices);
+            collectionType = CollectionType.MAP;
         } else {
             // Can't retrieve elements for objects that are neither arrays, nor list, nor maps.
             return nextComponent;
@@ -208,7 +212,7 @@
         final String fixedKey = getFixedKey(callSiteDescriptor);
         // Convert the key to a number if we're working with a list or array
         final Object typedFixedKey;
-        if(!isMap && fixedKey != null) {
+        if(collectionType != CollectionType.MAP && fixedKey != null) {
             typedFixedKey = convertKeyToInteger(fixedKey, linkerServices);
             if(typedFixedKey == null) {
                 // key is not numeric, it can never succeed
@@ -227,15 +231,21 @@
         }
 
         final MethodHandle checkGuard;
-        if(invocation == GET_LIST_ELEMENT) {
+        switch(collectionType) {
+        case LIST:
             checkGuard = convertArgToInt(RANGE_CHECK_LIST, linkerServices, callSiteDescriptor);
-        } else if(invocation == GET_MAP_ELEMENT) {
+            break;
+        case MAP:
             // TODO: A more complex solution could be devised for maps, one where we do a get() first, and fold it
             // into a GWT that tests if it returned null, and if it did, do another GWT with containsKey()
             // that returns constant null (on true), or falls back to next component (on false)
-            checkGuard = CONTAINS_MAP;
-        } else {
+            checkGuard = linkerServices.filterInternalObjects(CONTAINS_MAP);
+            break;
+        case ARRAY:
             checkGuard = convertArgToInt(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
+            break;
+        default:
+            throw new AssertionError();
         }
         final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation),
                 nextComponent.getGuardedInvocation().getInvocation());
@@ -243,6 +253,18 @@
                 gic.getValidatorClass(), gic.getValidationType());
     }
 
+    private static GuardedInvocationComponent createInternalFilteredGuardedInvocationComponent(
+            final MethodHandle invocation, final LinkerServices linkerServices) {
+        return new GuardedInvocationComponent(linkerServices.filterInternalObjects(invocation));
+    }
+
+    private static GuardedInvocationComponent createInternalFilteredGuardedInvocationComponent(
+            final MethodHandle invocation, final MethodHandle guard, final Class<?> validatorClass,
+            final ValidationType validationType, final LinkerServices linkerServices) {
+        return new GuardedInvocationComponent(linkerServices.filterInternalObjects(invocation), guard,
+                validatorClass, validationType);
+    }
+
     private static String getFixedKey(final CallSiteDescriptor callSiteDescriptor) {
         return callSiteDescriptor.getNameTokenCount() == 2 ? null : callSiteDescriptor.getNameToken(
                 CallSiteDescriptor.NAME_OPERAND);
@@ -381,37 +403,38 @@
         // dealing with an array, or a list or map, but hey...
         // Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers
         // in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices.
-        final boolean isMap;
+        final CollectionType collectionType;
         if(declaredType.isArray()) {
-            gic = new GuardedInvocationComponent(MethodHandles.arrayElementSetter(declaredType));
-            isMap = false;
+            gic = createInternalFilteredGuardedInvocationComponent(MethodHandles.arrayElementSetter(declaredType), linkerServices);
+            collectionType = CollectionType.ARRAY;
         } else if(List.class.isAssignableFrom(declaredType)) {
-            gic = new GuardedInvocationComponent(SET_LIST_ELEMENT);
-            isMap = false;
+            gic = createInternalFilteredGuardedInvocationComponent(SET_LIST_ELEMENT, linkerServices);
+            collectionType = CollectionType.LIST;
         } else if(Map.class.isAssignableFrom(declaredType)) {
-            gic = new GuardedInvocationComponent(PUT_MAP_ELEMENT);
-            isMap = true;
+            gic = createInternalFilteredGuardedInvocationComponent(PUT_MAP_ELEMENT, linkerServices);
+            collectionType = CollectionType.MAP;
         } else if(clazz.isArray()) {
-            gic = getClassGuardedInvocationComponent(MethodHandles.arrayElementSetter(clazz), callSiteType);
-            isMap = false;
+            gic = getClassGuardedInvocationComponent(linkerServices.filterInternalObjects(
+                    MethodHandles.arrayElementSetter(clazz)), callSiteType);
+            collectionType = CollectionType.ARRAY;
         } else if(List.class.isAssignableFrom(clazz)) {
-            gic = new GuardedInvocationComponent(SET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class,
-                    ValidationType.INSTANCE_OF);
-            isMap = false;
+            gic = createInternalFilteredGuardedInvocationComponent(SET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class, ValidationType.INSTANCE_OF,
+                    linkerServices);
+            collectionType = CollectionType.LIST;
         } else if(Map.class.isAssignableFrom(clazz)) {
-            gic = new GuardedInvocationComponent(PUT_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType), Map.class,
-                    ValidationType.INSTANCE_OF);
-            isMap = true;
+            gic = createInternalFilteredGuardedInvocationComponent(PUT_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType),
+                    Map.class, ValidationType.INSTANCE_OF, linkerServices);
+            collectionType = CollectionType.MAP;
         } else {
             // Can't set elements for objects that are neither arrays, nor list, nor maps.
             gic = null;
-            isMap = false;
+            collectionType = null;
         }
 
         // In contrast to, say, getElementGetter, we only compute the nextComponent if the target object is not a map,
         // as maps will always succeed in setting the element and will never need to fall back to the next component
         // operation.
-        final GuardedInvocationComponent nextComponent = isMap ? null : getGuardedInvocationComponent(
+        final GuardedInvocationComponent nextComponent = collectionType == CollectionType.MAP ? null : getGuardedInvocationComponent(
                 callSiteDescriptor, linkerServices, operations);
         if(gic == null) {
             return nextComponent;
@@ -421,7 +444,7 @@
         final String fixedKey = getFixedKey(callSiteDescriptor);
         // Convert the key to a number if we're working with a list or array
         final Object typedFixedKey;
-        if(!isMap && fixedKey != null) {
+        if(collectionType != CollectionType.MAP && fixedKey != null) {
             typedFixedKey = convertKeyToInteger(fixedKey, linkerServices);
             if(typedFixedKey == null) {
                 // key is not numeric, it can never succeed
@@ -439,7 +462,8 @@
             return gic.replaceInvocation(binder.bind(invocation));
         }
 
-        final MethodHandle checkGuard = convertArgToInt(invocation == SET_LIST_ELEMENT ? RANGE_CHECK_LIST :
+        assert collectionType == CollectionType.LIST || collectionType == CollectionType.ARRAY;
+        final MethodHandle checkGuard = convertArgToInt(collectionType == CollectionType.LIST ? RANGE_CHECK_LIST :
             RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
         final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation),
                 nextComponent.getGuardedInvocation().getInvocation());
diff --git a/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java b/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java
index 2896732..d65db5b 100644
--- a/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java
+++ b/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java
@@ -107,7 +107,7 @@
     private final AccessibleObject target;
     private final MethodType type;
 
-    public CallerSensitiveDynamicMethod(final AccessibleObject target) {
+    CallerSensitiveDynamicMethod(final AccessibleObject target) {
         super(getName(target));
         this.target = target;
         this.type = getMethodType(target);
@@ -115,8 +115,9 @@
 
     private static String getName(final AccessibleObject target) {
         final Member m = (Member)target;
-        return getMethodNameWithSignature(getMethodType(target), getClassAndMethodName(m.getDeclaringClass(),
-                m.getName()));
+        final boolean constructor = m instanceof Constructor;
+        return getMethodNameWithSignature(getMethodType(target), constructor ? m.getName() :
+            getClassAndMethodName(m.getDeclaringClass(), m.getName()), !constructor);
     }
 
     @Override
diff --git a/src/jdk/internal/dynalink/beans/FacetIntrospector.java b/src/jdk/internal/dynalink/beans/FacetIntrospector.java
index 29c98d0..06a9632 100644
--- a/src/jdk/internal/dynalink/beans/FacetIntrospector.java
+++ b/src/jdk/internal/dynalink/beans/FacetIntrospector.java
@@ -152,7 +152,7 @@
     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
+        // non-restricted class, so if the declaring class is identical to the class being inspected, then forego
         // a potentially expensive restricted-package check.
         return declaring == clazz || !CheckRestrictedPackage.isRestrictedClass(declaring);
     }
diff --git a/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java b/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java
index 83156e3..a856f00 100644
--- a/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java
+++ b/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java
@@ -86,7 +86,9 @@
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
+import java.text.Collator;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
@@ -242,6 +244,35 @@
         return methods.getFirst().isConstructor();
     }
 
+    @Override
+    public String toString() {
+        // First gather the names and sort them. This makes it consistent and easier to read.
+        final List<String> names = new ArrayList<>(methods.size());
+        int len = 0;
+        for (final SingleDynamicMethod m: methods) {
+            final String name = m.getName();
+            len += name.length();
+            names.add(name);
+        }
+        // Case insensitive sorting, so e.g. "Object" doesn't come before "boolean".
+        final Collator collator = Collator.getInstance();
+        collator.setStrength(Collator.SECONDARY);
+        Collections.sort(names, collator);
+
+        final String className = getClass().getName();
+        // Class name length + length of signatures + 2 chars/per signature for indentation and newline +
+        // 3 for brackets and initial newline
+        final int totalLength = className.length() + len + 2 * names.size() + 3;
+        final StringBuilder b = new StringBuilder(totalLength);
+        b.append('[').append(className).append('\n');
+        for(final String name: names) {
+            b.append(' ').append(name).append('\n');
+        }
+        b.append(']');
+        assert b.length() == totalLength;
+        return b.toString();
+    };
+
     ClassLoader getClassLoader() {
         return classLoader;
     }
diff --git a/src/jdk/internal/dynalink/beans/OverloadedMethod.java b/src/jdk/internal/dynalink/beans/OverloadedMethod.java
index c8d5007..b2aeb16 100644
--- a/src/jdk/internal/dynalink/beans/OverloadedMethod.java
+++ b/src/jdk/internal/dynalink/beans/OverloadedMethod.java
@@ -139,7 +139,8 @@
         final MethodHandle bound = SELECT_METHOD.bindTo(this);
         final MethodHandle collecting = SingleDynamicMethod.collectArguments(bound, argNum).asType(
                 callSiteType.changeReturnType(MethodHandle.class));
-        invoker = MethodHandles.foldArguments(MethodHandles.exactInvoker(this.callSiteType), collecting);
+        invoker = linkerServices.asTypeLosslessReturn(MethodHandles.foldArguments(
+                MethodHandles.exactInvoker(this.callSiteType), collecting), callSiteType);
     }
 
     MethodHandle getInvoker() {
diff --git a/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java b/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java
index f4a8b0a..3e57337 100644
--- a/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java
+++ b/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java
@@ -122,13 +122,13 @@
      * @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));
+        super(getName(target, clazz, name, constructor));
         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));
+    private static String getName(final MethodHandle target, final Class<?> clazz, final String name, final boolean constructor) {
+        return getMethodNameWithSignature(target.type(), constructor ? name : getClassAndMethodName(clazz, name), !constructor);
     }
 
     @Override
diff --git a/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java b/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java
index 79dca9a..bf40d60 100644
--- a/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java
+++ b/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java
@@ -98,7 +98,6 @@
  * target method to a call site type (including mapping variable arity methods to a call site signature with different
  * arity).
  * @author Attila Szegedi
- * @version $Id: $
  */
 abstract class SingleDynamicMethod extends DynamicMethod {
 
@@ -143,14 +142,18 @@
         return getMethodType().parameterList().equals(method.getMethodType().parameterList());
     }
 
-    static String getMethodNameWithSignature(final MethodType type, final String methodName) {
+    static String getMethodNameWithSignature(final MethodType type, final String methodName, final boolean withReturnType) {
         final String typeStr = type.toString();
         final int retTypeIndex = typeStr.lastIndexOf(')') + 1;
         int secondParamIndex = typeStr.indexOf(',') + 1;
         if(secondParamIndex == 0) {
             secondParamIndex = retTypeIndex - 1;
         }
-        return typeStr.substring(retTypeIndex) + " " + methodName + "(" + typeStr.substring(secondParamIndex, retTypeIndex);
+        final StringBuilder b = new StringBuilder();
+        if (withReturnType) {
+            b.append(typeStr, retTypeIndex, typeStr.length()).append(' ');
+        }
+        return b.append(methodName).append('(').append(typeStr, secondParamIndex, retTypeIndex).toString();
     }
 
     /**
@@ -165,10 +168,11 @@
      * @return the adapted method handle.
      */
     static MethodHandle getInvocation(final MethodHandle target, final MethodType callSiteType, final LinkerServices linkerServices) {
-        final MethodType methodType = target.type();
+        final MethodHandle filteredTarget = linkerServices.filterInternalObjects(target);
+        final MethodType methodType = filteredTarget.type();
         final int paramsLen = methodType.parameterCount();
         final boolean varArgs = target.isVarargsCollector();
-        final MethodHandle fixTarget = varArgs ? target.asFixedArity() : target;
+        final MethodHandle fixTarget = varArgs ? filteredTarget.asFixedArity() : filteredTarget;
         final int fixParamsLen = varArgs ? paramsLen - 1 : paramsLen;
         final int argsLen = callSiteType.parameterCount();
         if(argsLen < fixParamsLen) {
@@ -204,7 +208,7 @@
             if(varArgType.isAssignableFrom(callSiteLastArgType)) {
                 // Call site signature guarantees we'll always be passed a single compatible array; just link directly
                 // to the method, introducing necessary conversions. Also, preserve it being a variable arity method.
-                return createConvertingInvocation(target, linkerServices, callSiteType).asVarargsCollector(
+                return createConvertingInvocation(filteredTarget, linkerServices, callSiteType).asVarargsCollector(
                         callSiteLastArgType);
             }
 
diff --git a/src/jdk/internal/dynalink/beans/StaticClass.java b/src/jdk/internal/dynalink/beans/StaticClass.java
index f70f264..153c12c 100644
--- a/src/jdk/internal/dynalink/beans/StaticClass.java
+++ b/src/jdk/internal/dynalink/beans/StaticClass.java
@@ -84,6 +84,7 @@
 package jdk.internal.dynalink.beans;
 
 import java.io.Serializable;
+import java.util.Objects;
 
 /**
  * Object that represents the static facet of a class (its static methods, properties, and fields, as well as
@@ -106,8 +107,7 @@
     private final Class<?> clazz;
 
     /*private*/ StaticClass(final Class<?> clazz) {
-        clazz.getClass(); // NPE check
-        this.clazz = clazz;
+        this.clazz = Objects.requireNonNull(clazz);
     }
 
     /**
diff --git a/src/jdk/internal/dynalink/linker/GuardedInvocation.java b/src/jdk/internal/dynalink/linker/GuardedInvocation.java
index 00ee9dc..adf34a0 100644
--- a/src/jdk/internal/dynalink/linker/GuardedInvocation.java
+++ b/src/jdk/internal/dynalink/linker/GuardedInvocation.java
@@ -91,6 +91,7 @@
 import java.lang.invoke.SwitchPoint;
 import java.lang.invoke.WrongMethodTypeException;
 import java.util.List;
+import java.util.Objects;
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.support.Guards;
 
@@ -170,8 +171,7 @@
      * @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.invocation = Objects.requireNonNull(invocation);
         this.guard = guard;
         this.switchPoints = switchPoint == null ? null : new SwitchPoint[] { switchPoint };
         this.exception = exception;
@@ -190,8 +190,7 @@
      * @throws NullPointerException if invocation is null.
      */
     public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint[] switchPoints, final Class<? extends Throwable> exception) {
-        invocation.getClass(); // NPE check
-        this.invocation = invocation;
+        this.invocation = Objects.requireNonNull(invocation);
         this.guard = guard;
         this.switchPoints = switchPoints == null ? null : switchPoints.clone();
         this.exception = exception;
@@ -354,7 +353,7 @@
 
     /**
      * Applies argument filters to both the invocation and the guard (if there is one).
-     * @param pos the position of the first argumen being filtered
+     * @param pos the position of the first argument being filtered
      * @param filters the argument filters
      * @return a filtered invocation
      */
diff --git a/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java b/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java
index 88357ff..b070ed6 100644
--- a/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java
+++ b/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java
@@ -110,7 +110,7 @@
 
     /**
      * Check if invocation is cacheable
-     * @return true if cachable, false otherwise
+     * @return true if cacheable, false otherwise
      */
     public boolean isCacheable() {
         return cacheable;
diff --git a/src/jdk/internal/dynalink/linker/LinkerServices.java b/src/jdk/internal/dynalink/linker/LinkerServices.java
index 9e35d7f..7fd2c04 100644
--- a/src/jdk/internal/dynalink/linker/LinkerServices.java
+++ b/src/jdk/internal/dynalink/linker/LinkerServices.java
@@ -181,6 +181,15 @@
     public Comparison compareConversion(Class<?> sourceType, Class<?> targetType1, Class<?> targetType2);
 
     /**
+     * Modifies the method handle so that any parameters that can receive potentially internal language runtime objects
+     * will have a filter added on them to prevent them from escaping, potentially by wrapping them.
+     * It can also potentially add an unwrapping filter to the return value.
+     * @param target the target method handle
+     * @return a method handle with parameters and/or return type potentially filtered for wrapping and unwrapping.
+     */
+    public MethodHandle filterInternalObjects(final MethodHandle target);
+
+    /**
      * 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.
      */
diff --git a/src/jdk/internal/dynalink/linker/MethodHandleTransformer.java b/src/jdk/internal/dynalink/linker/MethodHandleTransformer.java
new file mode 100644
index 0000000..9d1efbe
--- /dev/null
+++ b/src/jdk/internal/dynalink/linker/MethodHandleTransformer.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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-2015 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.linker;
+
+import java.lang.invoke.MethodHandle;
+
+/**
+ * A generic interface describing operations that transform method handles.
+ */
+public interface MethodHandleTransformer {
+    /**
+     * Transforms a method handle.
+     * @param target the method handle being transformed.
+     * @return transformed method handle.
+     */
+    public MethodHandle transform(final MethodHandle target);
+}
diff --git a/src/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java b/src/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java
index 9cbd5f0..bfc0dea 100644
--- a/src/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java
+++ b/src/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java
@@ -91,6 +91,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 import java.util.StringTokenizer;
 import java.util.WeakHashMap;
 import jdk.internal.dynalink.CallSiteDescriptor;
@@ -123,9 +124,9 @@
      * in fact return a weakly-referenced canonical instance.
      */
     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
+        Objects.requireNonNull(name);
+        Objects.requireNonNull(methodType);
+        Objects.requireNonNull(lookup);
         final String[] tokenizedName = tokenizeName(name);
         if(isPublicLookup(lookup)) {
             return getCanonicalPublicDescriptor(createPublicCallSiteDescriptor(tokenizedName, methodType));
diff --git a/src/jdk/internal/dynalink/support/DefaultInternalObjectFilter.java b/src/jdk/internal/dynalink/support/DefaultInternalObjectFilter.java
new file mode 100644
index 0000000..94378f1
--- /dev/null
+++ b/src/jdk/internal/dynalink/support/DefaultInternalObjectFilter.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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-2015 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 java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import jdk.internal.dynalink.DynamicLinkerFactory;
+import jdk.internal.dynalink.linker.MethodHandleTransformer;
+
+/**
+ * Default implementation for a {@link DynamicLinkerFactory#setInternalObjectsFilter(MethodHandleTransformer)}.
+ * Given a method handle of {@code Object(Object)} type for filtering parameter and another one of the same type for
+ * filtering return values, applies them to passed method handles where their parameter types and/or return value types
+ * are declared to be {@link Object}.
+ */
+public class DefaultInternalObjectFilter implements MethodHandleTransformer {
+    private static final MethodHandle FILTER_VARARGS = new Lookup(MethodHandles.lookup()).findStatic(
+            DefaultInternalObjectFilter.class, "filterVarArgs", MethodType.methodType(Object[].class, MethodHandle.class, Object[].class));
+
+    private final MethodHandle parameterFilter;
+    private final MethodHandle returnFilter;
+    private final MethodHandle varArgFilter;
+
+    /**
+     * Creates a new filter.
+     * @param parameterFilter the filter for method parameters. Must be of type {@code Object(Object)}, or null.
+     * @param returnFilter the filter for return values. Must be of type {@code Object(Object)}, or null.
+     * @throws IllegalArgumentException if one or both filters are not of the expected type.
+     */
+    public DefaultInternalObjectFilter(final MethodHandle parameterFilter, final MethodHandle returnFilter) {
+        this.parameterFilter = checkHandle(parameterFilter, "parameterFilter");
+        this.returnFilter = checkHandle(returnFilter, "returnFilter");
+        this.varArgFilter = parameterFilter == null ? null : FILTER_VARARGS.bindTo(parameterFilter);
+    }
+
+    @Override
+    public MethodHandle transform(final MethodHandle target) {
+        assert target != null;
+        MethodHandle[] filters = null;
+        final MethodType type = target.type();
+        final boolean isVarArg = target.isVarargsCollector();
+        final int paramCount = type.parameterCount();
+        final MethodHandle paramsFiltered;
+        // Filter parameters
+        if (parameterFilter != null) {
+            int firstFilter = -1;
+            // Ignore receiver, start from argument 1
+            for(int i = 1; i < paramCount; ++i) {
+                final Class<?> paramType = type.parameterType(i);
+                final boolean filterVarArg = isVarArg && i == paramCount - 1 && paramType == Object[].class;
+                if (filterVarArg || paramType == Object.class) {
+                    if (filters == null) {
+                        firstFilter = i;
+                        filters = new MethodHandle[paramCount - firstFilter];
+                    }
+                    filters[i - firstFilter] = filterVarArg ? varArgFilter : parameterFilter;
+                }
+            }
+            paramsFiltered = filters != null ? MethodHandles.filterArguments(target, firstFilter, filters) : target;
+        } else {
+            paramsFiltered = target;
+        }
+        // Filter return value if needed
+        final MethodHandle returnFiltered = returnFilter != null && type.returnType() == Object.class ? MethodHandles.filterReturnValue(paramsFiltered, returnFilter) : paramsFiltered;
+        // Preserve varargs collector state
+        return isVarArg && !returnFiltered.isVarargsCollector() ? returnFiltered.asVarargsCollector(type.parameterType(paramCount - 1)) : returnFiltered;
+
+    }
+
+    private static MethodHandle checkHandle(final MethodHandle handle, final String handleKind) {
+        if (handle != null) {
+            final MethodType objectObjectType = MethodType.methodType(Object.class, Object.class);
+            if (!handle.type().equals(objectObjectType)) {
+                throw new IllegalArgumentException("Method type for " + handleKind + " must be " + objectObjectType);
+            }
+        }
+        return handle;
+    }
+
+    @SuppressWarnings("unused")
+    private static Object[] filterVarArgs(final MethodHandle parameterFilter, final Object[] args) throws Throwable {
+        Object[] newArgs = null;
+        for(int i = 0; i < args.length; ++i) {
+            final Object arg = args[i];
+            final Object newArg = parameterFilter.invokeExact(arg);
+            if (arg != newArg) {
+                if (newArgs == null) {
+                    newArgs = args.clone();
+                }
+                newArgs[i] = newArg;
+            }
+        }
+        return newArgs == null ? args : newArgs;
+    }
+}
diff --git a/src/jdk/internal/dynalink/support/LinkerServicesImpl.java b/src/jdk/internal/dynalink/support/LinkerServicesImpl.java
index 38d93c8..d7e89fd 100644
--- a/src/jdk/internal/dynalink/support/LinkerServicesImpl.java
+++ b/src/jdk/internal/dynalink/support/LinkerServicesImpl.java
@@ -90,6 +90,7 @@
 import jdk.internal.dynalink.linker.GuardingDynamicLinker;
 import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.internal.dynalink.linker.LinkerServices;
+import jdk.internal.dynalink.linker.MethodHandleTransformer;
 
 /**
  * Default implementation of the {@link LinkerServices} interface.
@@ -103,17 +104,21 @@
 
     private final TypeConverterFactory typeConverterFactory;
     private final GuardingDynamicLinker topLevelLinker;
+    private final MethodHandleTransformer internalObjectsFilter;
 
     /**
      * Creates a new linker services object.
      *
      * @param typeConverterFactory the type converter factory exposed by the services.
      * @param topLevelLinker the top level linker used by the services.
+     * @param internalObjectsFilter a method handle transformer that is supposed to act as the implementation of this
+     * services' {@link #filterInternalObjects(java.lang.invoke.MethodHandle)} method.
      */
     public LinkerServicesImpl(final TypeConverterFactory typeConverterFactory,
-            final GuardingDynamicLinker topLevelLinker) {
+            final GuardingDynamicLinker topLevelLinker, final MethodHandleTransformer internalObjectsFilter) {
         this.typeConverterFactory = typeConverterFactory;
         this.topLevelLinker = topLevelLinker;
+        this.internalObjectsFilter = internalObjectsFilter;
     }
 
     @Override
@@ -152,6 +157,11 @@
         }
     }
 
+    @Override
+    public MethodHandle filterInternalObjects(final MethodHandle target) {
+        return internalObjectsFilter != null ? internalObjectsFilter.transform(target) : target;
+    }
+
     /**
      * Returns the currently processed link request, or null if the method is invoked outside of the linking process.
      * @return the currently processed link request, or null.
diff --git a/src/jdk/nashorn/api/scripting/AbstractJSObject.java b/src/jdk/nashorn/api/scripting/AbstractJSObject.java
index a776164..680198d 100644
--- a/src/jdk/nashorn/api/scripting/AbstractJSObject.java
+++ b/src/jdk/nashorn/api/scripting/AbstractJSObject.java
@@ -28,6 +28,8 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Set;
+import jdk.nashorn.internal.runtime.JSONListAdapter;
+import jdk.nashorn.internal.runtime.JSType;
 
 /**
  * This is the base class for nashorn ScriptObjectMirror class.
@@ -36,7 +38,10 @@
  * treat objects of such classes just like nashorn script objects. Usual nashorn
  * operations like obj[i], obj.foo, obj.func(), delete obj.foo will be glued
  * to appropriate method call of this class.
+ *
+ * @since 1.8u40
  */
+@jdk.Exported
 public abstract class AbstractJSObject implements JSObject {
     /**
      * Call this object as a JavaScript function. This is equivalent to
@@ -158,9 +163,8 @@
      * @return set of property names
      */
     @Override
-    @SuppressWarnings("unchecked")
     public Set<String> keySet() {
-        return Collections.EMPTY_SET;
+        return Collections.emptySet();
     }
 
     /**
@@ -169,9 +173,8 @@
      * @return set of property values.
      */
     @Override
-    @SuppressWarnings("unchecked")
     public Collection<Object> values() {
-        return Collections.EMPTY_SET;
+        return Collections.emptySet();
     }
 
     // JavaScript instanceof check
@@ -179,7 +182,7 @@
     /**
      * Checking whether the given object is an instance of 'this' object.
      *
-     * @param instance instace to check
+     * @param instance instance to check
      * @return true if the given 'instance' is an instance of this 'function' object
      */
     @Override
@@ -246,9 +249,43 @@
      * Returns this object's numeric value.
      *
      * @return this object's numeric value.
+     * @deprecated use {@link #getDefaultValue(Class)} with {@link Number} hint instead.
      */
-    @Override
+    @Override @Deprecated
     public double toNumber() {
-        return Double.NaN;
+        return JSType.toNumber(JSType.toPrimitive(this, Number.class));
+    }
+
+    /**
+     * Implements this object's {@code [[DefaultValue]]} method. The default implementation follows ECMAScript 5.1
+     * section 8.6.2 but subclasses are free to provide their own implementations.
+     *
+     * @param hint the type hint. Should be either {@code null}, {@code Number.class} or {@code String.class}.
+     * @return this object's default value.
+     * @throws UnsupportedOperationException if the conversion can't be performed. The engine will convert this
+     * exception into a JavaScript {@code TypeError}.
+     */
+    public Object getDefaultValue(final Class<?> hint) {
+        return DefaultValueImpl.getDefaultValue(this, hint);
+    }
+
+    /**
+     * When passed an {@link AbstractJSObject}, invokes its {@link #getDefaultValue(Class)} method. When passed any
+     * other {@link JSObject}, it will obtain its {@code [[DefaultValue]]} method as per ECMAScript 5.1 section
+     * 8.6.2.
+     *
+     * @param jsobj the {@link JSObject} whose {@code [[DefaultValue]]} is obtained.
+     * @param hint the type hint. Should be either {@code null}, {@code Number.class} or {@code String.class}.
+     * @return this object's default value.
+     * @throws UnsupportedOperationException if the conversion can't be performed. The engine will convert this
+     * exception into a JavaScript {@code TypeError}.
+     */
+    public static Object getDefaultValue(final JSObject jsobj, final Class<?> hint) {
+        if (jsobj instanceof AbstractJSObject) {
+            return ((AbstractJSObject)jsobj).getDefaultValue(hint);
+        } else if (jsobj instanceof JSONListAdapter) {
+            return ((JSONListAdapter)jsobj).getDefaultValue(hint);
+        }
+        return DefaultValueImpl.getDefaultValue(jsobj, hint);
     }
 }
diff --git a/src/jdk/nashorn/api/scripting/ClassFilter.java b/src/jdk/nashorn/api/scripting/ClassFilter.java
index ddf1bc3..1a03c17 100644
--- a/src/jdk/nashorn/api/scripting/ClassFilter.java
+++ b/src/jdk/nashorn/api/scripting/ClassFilter.java
@@ -28,7 +28,10 @@
  * 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.
+ *
+ * @since 1.8u40
  */
+@jdk.Exported
 public interface ClassFilter {
      /**
       * Should the Java class of the specified name be exposed to scripts?
diff --git a/src/jdk/nashorn/api/scripting/DefaultValueImpl.java b/src/jdk/nashorn/api/scripting/DefaultValueImpl.java
new file mode 100644
index 0000000..c01dcb4
--- /dev/null
+++ b/src/jdk/nashorn/api/scripting/DefaultValueImpl.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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;
+
+import jdk.nashorn.internal.runtime.JSType;
+
+/**
+ * Default implementation of {@link JSObject#getDefaultValue(Class)}. Isolated into a separate class mostly so
+ * that we can have private static instances of function name arrays, something we couldn't declare without it
+ * being visible in {@link JSObject} interface.
+ */
+class DefaultValueImpl {
+    private static final String[] DEFAULT_VALUE_FNS_NUMBER = new String[] { "valueOf", "toString" };
+    private static final String[] DEFAULT_VALUE_FNS_STRING = new String[] { "toString", "valueOf" };
+
+    static Object getDefaultValue(final JSObject jsobj, final Class<?> hint) throws UnsupportedOperationException {
+        final boolean isNumber = hint == null || hint == Number.class;
+        for(final String methodName: isNumber ? DEFAULT_VALUE_FNS_NUMBER : DEFAULT_VALUE_FNS_STRING) {
+            final Object objMember = jsobj.getMember(methodName);
+            if (objMember instanceof JSObject) {
+                final JSObject member = (JSObject)objMember;
+                if (member.isFunction()) {
+                    final Object value = member.call(jsobj);
+                    if (JSType.isPrimitive(value)) {
+                        return value;
+                    }
+                }
+            }
+        }
+        throw new UnsupportedOperationException(isNumber ? "cannot.get.default.number" : "cannot.get.default.string");
+    }
+}
diff --git a/src/jdk/nashorn/api/scripting/JSObject.java b/src/jdk/nashorn/api/scripting/JSObject.java
index 8d81864..3c4484a 100644
--- a/src/jdk/nashorn/api/scripting/JSObject.java
+++ b/src/jdk/nashorn/api/scripting/JSObject.java
@@ -33,7 +33,10 @@
  * treat objects of such classes just like nashorn script objects. Usual nashorn
  * operations like obj[i], obj.foo, obj.func(), delete obj.foo will be glued
  * to appropriate method call of this interface.
+ *
+ * @since 1.8u40
  */
+@jdk.Exported
 public interface JSObject {
     /**
      * Call this object as a JavaScript function. This is equivalent to
@@ -138,7 +141,7 @@
     /**
      * Checking whether the given object is an instance of 'this' object.
      *
-     * @param instance instace to check
+     * @param instance instance to check
      * @return true if the given 'instance' is an instance of this 'function' object
      */
     public boolean isInstance(final Object instance);
@@ -183,6 +186,8 @@
      * Returns this object's numeric value.
      *
      * @return this object's numeric value.
+     * @deprecated use {@link AbstractJSObject#getDefaultValue(JSObject, Class)} with {@link Number} hint instead.
      */
+    @Deprecated
     public double toNumber();
 }
diff --git a/src/jdk/nashorn/api/scripting/NashornException.java b/src/jdk/nashorn/api/scripting/NashornException.java
index 098f850..1509a7d 100644
--- a/src/jdk/nashorn/api/scripting/NashornException.java
+++ b/src/jdk/nashorn/api/scripting/NashornException.java
@@ -41,13 +41,18 @@
  * script object or Java access to script object properties via java.util.Map
  * interface. In these cases, user code will get an instance of this or
  * implementation defined subclass.
+ *
+ * @since 1.8u40
  */
+@jdk.Exported
 @SuppressWarnings("serial")
 public abstract class NashornException extends RuntimeException {
     // script file name
     private String fileName;
     // script line number
     private int line;
+    // are the line and fileName unknown?
+    private boolean lineAndFileNameUnknown;
     // script column number
     private int column;
     // underlying ECMA error object - lazily initialized
@@ -89,27 +94,10 @@
      */
     protected NashornException(final String msg, final Throwable cause) {
         super(msg, cause == null ? null : cause);
-        // This is not so pretty - but it gets the job done. Note that the stack
-        // trace has been already filled by "fillInStackTrace" call from
-        // Throwable
-        // constructor and so we don't pay additional cost for it.
-
         // Hard luck - no column number info
         this.column = -1;
-
-        // Find the first JavaScript frame by walking and set file, line from it
-        // Usually, we should be able to find it in just few frames depth.
-        for (final StackTraceElement ste : getStackTrace()) {
-            if (ECMAErrors.isScriptFrame(ste)) {
-                // Whatever here is compiled from JavaScript code
-                this.fileName = ste.getFileName();
-                this.line = ste.getLineNumber();
-                return;
-            }
-        }
-
-        this.fileName = null;
-        this.line = 0;
+        // We can retrieve the line number and file name from the stack trace if needed
+        this.lineAndFileNameUnknown = true;
     }
 
     /**
@@ -118,6 +106,7 @@
      * @return the file name
      */
     public final String getFileName() {
+        ensureLineAndFileName();
         return fileName;
     }
 
@@ -128,6 +117,7 @@
      */
     public final void setFileName(final String fileName) {
         this.fileName = fileName;
+        lineAndFileNameUnknown = false;
     }
 
     /**
@@ -136,6 +126,7 @@
      * @return the line number
      */
     public final int getLineNumber() {
+        ensureLineAndFileName();
         return line;
     }
 
@@ -145,6 +136,7 @@
      * @param line the line number
      */
     public final void setLineNumber(final int line) {
+        lineAndFileNameUnknown = false;
         this.line = line;
     }
 
@@ -271,4 +263,19 @@
     public void setEcmaError(final Object ecmaError) {
         this.ecmaError = ecmaError;
     }
+
+    private void ensureLineAndFileName() {
+        if (lineAndFileNameUnknown) {
+            for (final StackTraceElement ste : getStackTrace()) {
+                if (ECMAErrors.isScriptFrame(ste)) {
+                    // Whatever here is compiled from JavaScript code
+                    fileName = ste.getFileName();
+                    line = ste.getLineNumber();
+                    return;
+                }
+            }
+
+            lineAndFileNameUnknown = false;
+        }
+    }
 }
diff --git a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
index 2f00095..0f2f3d7 100644
--- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
+++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
@@ -39,6 +39,7 @@
 import java.security.ProtectionDomain;
 import java.text.MessageFormat;
 import java.util.Locale;
+import java.util.Objects;
 import java.util.ResourceBundle;
 import javax.script.AbstractScriptEngine;
 import javax.script.Bindings;
@@ -65,8 +66,10 @@
  * {@link NashornScriptEngineFactory#getScriptEngine()}. Note that this engine implements the {@link Compilable} and
  * {@link Invocable} interfaces, allowing for efficient precompilation and repeated execution of scripts.
  * @see NashornScriptEngineFactory
+ *
+ * @since 1.8u40
  */
-
+@jdk.Exported
 public final class NashornScriptEngine extends AbstractScriptEngine implements Compilable, Invocable {
     /**
      * Key used to associate Nashorn global object mirror with arbitrary Bindings instance.
@@ -137,7 +140,7 @@
         this._global_per_engine = nashornContext.getEnv()._global_per_engine;
 
         // create new global object
-        this.global = createNashornGlobal(context);
+        this.global = createNashornGlobal();
         // set the default ENGINE_SCOPE object for the default context
         context.setBindings(new ScriptObjectMirror(global, global), ScriptContext.ENGINE_SCOPE);
     }
@@ -164,7 +167,7 @@
             // We use same 'global' for all Bindings.
             return new SimpleBindings();
         }
-        return createGlobalMirror(null);
+        return createGlobalMirror();
     }
 
     // Compilable methods
@@ -314,7 +317,7 @@
 
         // We didn't find associated nashorn global mirror in the Bindings given!
         // Create new global instance mirror and associate with the Bindings.
-        final ScriptObjectMirror mirror = createGlobalMirror(ctxt);
+        final ScriptObjectMirror mirror = createGlobalMirror();
         bindings.put(NASHORN_GLOBAL, mirror);
         return mirror.getHomeGlobal();
     }
@@ -330,13 +333,13 @@
     }
 
     // Create a new ScriptObjectMirror wrapping a newly created Nashorn Global object
-    private ScriptObjectMirror createGlobalMirror(final ScriptContext ctxt) {
-        final Global newGlobal = createNashornGlobal(ctxt);
+    private ScriptObjectMirror createGlobalMirror() {
+        final Global newGlobal = createNashornGlobal();
         return new ScriptObjectMirror(newGlobal, newGlobal);
     }
 
     // Create a new Nashorn Global object
-    private Global createNashornGlobal(final ScriptContext ctxt) {
+    private Global createNashornGlobal() {
         final Global newGlobal = AccessController.doPrivileged(new PrivilegedAction<Global>() {
             @Override
             public Global run() {
@@ -352,13 +355,12 @@
         }, CREATE_GLOBAL_ACC_CTXT);
 
         nashornContext.initGlobal(newGlobal, this);
-        newGlobal.setScriptContext(ctxt);
 
         return newGlobal;
     }
 
     private Object invokeImpl(final Object selfObject, final String name, final Object... args) throws ScriptException, NoSuchMethodException {
-        name.getClass(); // null check
+        Objects.requireNonNull(name);
         assert !(selfObject instanceof ScriptObject) : "raw ScriptObject not expected here";
 
         Global invokeGlobal = null;
@@ -401,7 +403,7 @@
         return evalImpl(script, ctxt, getNashornGlobalFrom(ctxt));
     }
 
-    private static Object evalImpl(final Context.MultiGlobalCompiledScript mgcs, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
+    private 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 {
@@ -410,8 +412,13 @@
             }
 
             final ScriptFunction script = mgcs.getFunction(ctxtGlobal);
+            final ScriptContext oldCtxt = ctxtGlobal.getScriptContext();
             ctxtGlobal.setScriptContext(ctxt);
-            return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
+            try {
+                return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
+            } finally {
+                ctxtGlobal.setScriptContext(oldCtxt);
+            }
         } catch (final Exception e) {
             throwAsScriptException(e, ctxtGlobal);
             throw new AssertionError("should not reach here");
@@ -422,7 +429,7 @@
         }
     }
 
-    private static Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
+    private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
         if (script == null) {
             return null;
         }
@@ -433,8 +440,13 @@
                 Context.setGlobal(ctxtGlobal);
             }
 
+            final ScriptContext oldCtxt = ctxtGlobal.getScriptContext();
             ctxtGlobal.setScriptContext(ctxt);
-            return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
+            try {
+                return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
+            } finally {
+                ctxtGlobal.setScriptContext(oldCtxt);
+            }
         } catch (final Exception e) {
             throwAsScriptException(e, ctxtGlobal);
             throw new AssertionError("should not reach here");
diff --git a/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java b/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java
index 4ddcf94..f38244c 100644
--- a/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java
+++ b/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java
@@ -28,6 +28,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 import javax.script.ScriptEngine;
 import javax.script.ScriptEngineFactory;
 import jdk.nashorn.internal.runtime.Context;
@@ -44,7 +45,10 @@
  * </ul>
  * Programs executing in engines created using {@link #getScriptEngine(String[])} will have the passed arguments
  * accessible as a global variable named {@code "arguments"}.
+ *
+ * @since 1.8u40
  */
+@jdk.Exported
 public final class NashornScriptEngineFactory implements ScriptEngineFactory {
     @Override
     public String getEngineName() {
@@ -120,7 +124,7 @@
             // used to execute scripts concurrently on multiple threads.
             return null;
         default:
-            throw new IllegalArgumentException("Invalid key");
+            return null;
         }
     }
 
@@ -174,8 +178,7 @@
      *         denies {@code RuntimePermission("nashorn.setConfig")}
      */
     public ScriptEngine getScriptEngine(final ClassFilter classFilter) {
-        classFilter.getClass(); // null check
-        return newEngine(DEFAULT_OPTIONS, getAppClassLoader(), classFilter);
+        return newEngine(DEFAULT_OPTIONS, getAppClassLoader(), Objects.requireNonNull(classFilter));
     }
 
     /**
@@ -189,8 +192,7 @@
      *         denies {@code RuntimePermission("nashorn.setConfig")}
      */
     public ScriptEngine getScriptEngine(final String... args) {
-        args.getClass(); // null check
-        return newEngine(args, getAppClassLoader(), null);
+        return newEngine(Objects.requireNonNull(args), getAppClassLoader(), null);
     }
 
     /**
@@ -205,8 +207,7 @@
      *         denies {@code RuntimePermission("nashorn.setConfig")}
      */
     public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader) {
-        args.getClass(); // null check
-        return newEngine(args, appLoader, null);
+        return newEngine(Objects.requireNonNull(args), appLoader, null);
     }
 
     /**
@@ -222,9 +223,7 @@
      *         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);
+        return newEngine(Objects.requireNonNull(args), appLoader, Objects.requireNonNull(classFilter));
     }
 
     private ScriptEngine newEngine(final String[] args, final ClassLoader appLoader, final ClassFilter classFilter) {
diff --git a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
index e28da04..e3bd9c2 100644
--- a/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
+++ b/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
@@ -39,12 +39,15 @@
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.Callable;
 import javax.script.Bindings;
 import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.ConsString;
 import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.ECMAException;
+import jdk.nashorn.internal.runtime.JSONListAdapter;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
@@ -54,7 +57,10 @@
 
 /**
  * Mirror object that wraps a given Nashorn Script object.
+ *
+ * @since 1.8u40
  */
+@jdk.Exported
 public final class ScriptObjectMirror extends AbstractJSObject implements Bindings {
     private static AccessControlContext getContextAccCtxt() {
         final Permissions perms = new Permissions();
@@ -67,6 +73,7 @@
     private final ScriptObject sobj;
     private final Global  global;
     private final boolean strict;
+    private final boolean jsonCompatible;
 
     @Override
     public boolean equals(final Object other) {
@@ -105,9 +112,9 @@
             }
 
             if (sobj instanceof ScriptFunction) {
-                final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
-                final Object self = globalChanged? wrap(thiz, oldGlobal) : thiz;
-                return wrap(ScriptRuntime.apply((ScriptFunction)sobj, unwrap(self, global), unwrapArray(modArgs, global)), global);
+                final Object[] modArgs = globalChanged? wrapArrayLikeMe(args, oldGlobal) : args;
+                final Object self = globalChanged? wrapLikeMe(thiz, oldGlobal) : thiz;
+                return wrapLikeMe(ScriptRuntime.apply((ScriptFunction)sobj, unwrap(self, global), unwrapArray(modArgs, global)));
             }
 
             throw new RuntimeException("not a function: " + toString());
@@ -135,8 +142,8 @@
             }
 
             if (sobj instanceof ScriptFunction) {
-                final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
-                return wrap(ScriptRuntime.construct((ScriptFunction)sobj, unwrapArray(modArgs, global)), global);
+                final Object[] modArgs = globalChanged? wrapArrayLikeMe(args, oldGlobal) : args;
+                return wrapLikeMe(ScriptRuntime.construct((ScriptFunction)sobj, unwrapArray(modArgs, global)));
             }
 
             throw new RuntimeException("not a constructor: " + toString());
@@ -165,7 +172,7 @@
                                 return Context.getContext();
                             }
                         }, GET_CONTEXT_ACC_CTXT);
-                return wrap(context.eval(global, s, sobj, null, false), global);
+                return wrapLikeMe(context.eval(global, s, sobj, null));
             }
         });
     }
@@ -177,7 +184,7 @@
      * @return return value of function
      */
     public Object callMember(final String functionName, final Object... args) {
-        functionName.getClass(); // null check
+        Objects.requireNonNull(functionName);
         final Global oldGlobal = Context.getGlobal();
         final boolean globalChanged = (oldGlobal != global);
 
@@ -188,8 +195,8 @@
 
             final Object val = sobj.get(functionName);
             if (val instanceof ScriptFunction) {
-                final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args;
-                return wrap(ScriptRuntime.apply((ScriptFunction)val, sobj, unwrapArray(modArgs, global)), global);
+                final Object[] modArgs = globalChanged? wrapArrayLikeMe(args, oldGlobal) : args;
+                return wrapLikeMe(ScriptRuntime.apply((ScriptFunction)val, sobj, unwrapArray(modArgs, global)));
             } else if (val instanceof JSObject && ((JSObject)val).isFunction()) {
                 return ((JSObject)val).call(sobj, args);
             }
@@ -210,10 +217,10 @@
 
     @Override
     public Object getMember(final String name) {
-        name.getClass();
+        Objects.requireNonNull(name);
         return inGlobal(new Callable<Object>() {
             @Override public Object call() {
-                return wrap(sobj.get(name), global);
+                return wrapLikeMe(sobj.get(name));
             }
         });
     }
@@ -222,14 +229,14 @@
     public Object getSlot(final int index) {
         return inGlobal(new Callable<Object>() {
             @Override public Object call() {
-                return wrap(sobj.get(index), global);
+                return wrapLikeMe(sobj.get(index));
             }
         });
     }
 
     @Override
     public boolean hasMember(final String name) {
-        name.getClass();
+        Objects.requireNonNull(name);
         return inGlobal(new Callable<Boolean>() {
             @Override public Boolean call() {
                 return sobj.has(name);
@@ -248,14 +255,12 @@
 
     @Override
     public void removeMember(final String name) {
-        name.getClass();
-        remove(name);
+        remove(Objects.requireNonNull(name));
     }
 
     @Override
     public void setMember(final String name, final Object value) {
-        name.getClass();
-        put(name, value);
+        put(Objects.requireNonNull(name), value);
     }
 
     @Override
@@ -337,9 +342,10 @@
 
     @Override
     public boolean containsKey(final Object key) {
+        checkKey(key);
         return inGlobal(new Callable<Boolean>() {
             @Override public Boolean call() {
-                return sobj.containsKey(unwrap(key, global));
+                return sobj.containsKey(key);
             }
         });
     }
@@ -362,7 +368,7 @@
 
                 while (iter.hasNext()) {
                     final String key   = iter.next();
-                    final Object value = translateUndefined(wrap(sobj.get(key), global));
+                    final Object value = translateUndefined(wrapLikeMe(sobj.get(key)));
                     entries.add(new AbstractMap.SimpleImmutableEntry<>(key, value));
                 }
 
@@ -373,9 +379,10 @@
 
     @Override
     public Object get(final Object key) {
+        checkKey(key);
         return inGlobal(new Callable<Object>() {
             @Override public Object call() {
-                return translateUndefined(wrap(sobj.get(key), global));
+                return translateUndefined(wrapLikeMe(sobj.get(key)));
             }
         });
     }
@@ -407,26 +414,30 @@
 
     @Override
     public Object put(final String key, final Object value) {
+        checkKey(key);
         final ScriptObject oldGlobal = Context.getGlobal();
         final boolean globalChanged = (oldGlobal != global);
         return inGlobal(new Callable<Object>() {
             @Override public Object call() {
-                final Object modValue = globalChanged? wrap(value, oldGlobal) : value;
-                return translateUndefined(wrap(sobj.put(key, unwrap(modValue, global), strict), global));
+                final Object modValue = globalChanged? wrapLikeMe(value, oldGlobal) : value;
+                return translateUndefined(wrapLikeMe(sobj.put(key, unwrap(modValue, global), strict)));
             }
         });
     }
 
     @Override
     public void putAll(final Map<? extends String, ? extends Object> map) {
+        Objects.requireNonNull(map);
         final ScriptObject oldGlobal = Context.getGlobal();
         final boolean globalChanged = (oldGlobal != global);
         inGlobal(new Callable<Object>() {
             @Override public Object call() {
                 for (final Map.Entry<? extends String, ? extends Object> entry : map.entrySet()) {
                     final Object value = entry.getValue();
-                    final Object modValue = globalChanged? wrap(value, oldGlobal) : value;
-                    sobj.set(entry.getKey(), unwrap(modValue, global), getCallSiteFlags());
+                    final Object modValue = globalChanged? wrapLikeMe(value, oldGlobal) : value;
+                    final String key = entry.getKey();
+                    checkKey(key);
+                    sobj.set(key, unwrap(modValue, global), getCallSiteFlags());
                 }
                 return null;
             }
@@ -435,9 +446,10 @@
 
     @Override
     public Object remove(final Object key) {
+        checkKey(key);
         return inGlobal(new Callable<Object>() {
             @Override public Object call() {
-                return wrap(sobj.remove(unwrap(key, global), strict), global);
+                return translateUndefined(wrapLikeMe(sobj.remove(key, strict)));
             }
         });
     }
@@ -474,7 +486,7 @@
                 final Iterator<Object> iter   = sobj.valueIterator();
 
                 while (iter.hasNext()) {
-                    values.add(translateUndefined(wrap(iter.next(), global)));
+                    values.add(translateUndefined(wrapLikeMe(iter.next())));
                 }
 
                 return Collections.unmodifiableList(values);
@@ -491,7 +503,7 @@
     public Object getProto() {
         return inGlobal(new Callable<Object>() {
             @Override public Object call() {
-                return wrap(sobj.getProto(), global);
+                return wrapLikeMe(sobj.getProto());
             }
         });
     }
@@ -520,7 +532,7 @@
     public Object getOwnPropertyDescriptor(final String key) {
         return inGlobal(new Callable<Object>() {
             @Override public Object call() {
-                return wrap(sobj.getOwnPropertyDescriptor(key), global);
+                return wrapLikeMe(sobj.getOwnPropertyDescriptor(key));
             }
         });
     }
@@ -626,7 +638,7 @@
     }
 
     /**
-     * Utilitity to convert this script object to the given type.
+     * Utility to convert this script object to the given type.
      *
      * @param <T> destination type to convert to
      * @param type destination type to convert to
@@ -649,16 +661,76 @@
      * @return wrapped/converted object
      */
     public static Object wrap(final Object obj, final Object homeGlobal) {
+        return wrap(obj, homeGlobal, false);
+    }
+
+    /**
+     * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings. The
+     * created wrapper will implement the Java {@code List} interface if {@code obj} is a JavaScript
+     * {@code Array} object; this is compatible with Java JSON libraries expectations. Arrays retrieved through its
+     * properties (transitively) will also implement the list interface.
+     *
+     * @param obj object to be wrapped/converted
+     * @param homeGlobal global to which this object belongs. Not used for ConsStrings.
+     * @return wrapped/converted object
+     */
+    public static Object wrapAsJSONCompatible(final Object obj, final Object homeGlobal) {
+        return wrap(obj, homeGlobal, true);
+    }
+
+    /**
+     * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings.
+     *
+     * @param obj object to be wrapped/converted
+     * @param homeGlobal global to which this object belongs. Not used for ConsStrings.
+     * @param jsonCompatible if true, the created wrapper will implement the Java {@code List} interface if
+     * {@code obj} is a JavaScript {@code Array} object. Arrays retrieved through its properties (transitively)
+     * will also implement the list interface.
+     * @return wrapped/converted object
+     */
+    private static Object wrap(final Object obj, final Object homeGlobal, final boolean jsonCompatible) {
         if(obj instanceof ScriptObject) {
-            return homeGlobal instanceof Global ? new ScriptObjectMirror((ScriptObject)obj, (Global)homeGlobal) : obj;
-        }
-        if(obj instanceof ConsString) {
+            if (!(homeGlobal instanceof Global)) {
+                return obj;
+            }
+            final ScriptObject sobj = (ScriptObject)obj;
+            final Global global = (Global)homeGlobal;
+            final ScriptObjectMirror mirror = new ScriptObjectMirror(sobj, global, jsonCompatible);
+            if (jsonCompatible && sobj.isArray()) {
+                return new JSONListAdapter(mirror, global);
+            }
+            return mirror;
+        } else if(obj instanceof ConsString) {
             return obj.toString();
+        } else if (jsonCompatible && obj instanceof ScriptObjectMirror) {
+            // Since choosing JSON compatible representation is an explicit decision on user's part, if we're asked to
+            // wrap a mirror that was not JSON compatible, explicitly create its compatible counterpart following the
+            // principle of least surprise.
+            return ((ScriptObjectMirror)obj).asJSONCompatible();
         }
         return obj;
     }
 
     /**
+     * Wraps the passed object with the same jsonCompatible flag as this mirror.
+     * @param obj the object
+     * @param homeGlobal the object's home global.
+     * @return a wrapper for the object.
+     */
+    private Object wrapLikeMe(final Object obj, final Object homeGlobal) {
+        return wrap(obj, homeGlobal, jsonCompatible);
+    }
+
+    /**
+     * Wraps the passed object with the same home global and jsonCompatible flag as this mirror.
+     * @param obj the object
+     * @return a wrapper for the object.
+     */
+    private Object wrapLikeMe(final Object obj) {
+        return wrapLikeMe(obj, global);
+    }
+
+    /**
      * Unwrap a script object mirror if needed.
      *
      * @param obj object to be unwrapped
@@ -669,6 +741,8 @@
         if (obj instanceof ScriptObjectMirror) {
             final ScriptObjectMirror mirror = (ScriptObjectMirror)obj;
             return (mirror.global == homeGlobal)? mirror.sobj : obj;
+        } else if (obj instanceof JSONListAdapter) {
+            return ((JSONListAdapter)obj).unwrap(homeGlobal);
         }
 
         return obj;
@@ -682,6 +756,10 @@
      * @return wrapped array
      */
     public static Object[] wrapArray(final Object[] args, final Object homeGlobal) {
+        return wrapArray(args, homeGlobal, false);
+    }
+
+    private static Object[] wrapArray(final Object[] args, final Object homeGlobal, final boolean jsonCompatible) {
         if (args == null || args.length == 0) {
             return args;
         }
@@ -689,12 +767,16 @@
         final Object[] newArgs = new Object[args.length];
         int index = 0;
         for (final Object obj : args) {
-            newArgs[index] = wrap(obj, homeGlobal);
+            newArgs[index] = wrap(obj, homeGlobal, jsonCompatible);
             index++;
         }
         return newArgs;
     }
 
+    private Object[] wrapArrayLikeMe(final Object[] args, final Object homeGlobal) {
+        return wrapArray(args, homeGlobal, jsonCompatible);
+    }
+
     /**
      * Unwrap an array of script object mirrors if needed.
      *
@@ -736,12 +818,17 @@
     // package-privates below this.
 
     ScriptObjectMirror(final ScriptObject sobj, final Global global) {
+        this(sobj, global, false);
+    }
+
+    private ScriptObjectMirror(final ScriptObject sobj, final Global global, final boolean jsonCompatible) {
         assert sobj != null : "ScriptObjectMirror on null!";
         assert global != null : "home Global is null";
 
         this.sobj = sobj;
         this.global = global;
         this.strict = global.isStrictContext();
+        this.jsonCompatible = jsonCompatible;
     }
 
     // accessors for script engine
@@ -783,7 +870,25 @@
         }
     }
 
-    @Override
+    /**
+     * Ensures the key is not null, empty string, or a non-String object. The contract of the {@link Bindings}
+     * interface requires that these are not accepted as keys.
+     * @param key the key to check
+     * @throws NullPointerException if key is null
+     * @throws ClassCastException if key is not a String
+     * @throws IllegalArgumentException if key is empty string
+     */
+    private static void checkKey(final Object key) {
+        Objects.requireNonNull(key, "key can not be null");
+
+        if (!(key instanceof String)) {
+            throw new ClassCastException("key should be a String. It is " + key.getClass().getName() + " instead.");
+        } else if (((String)key).length() == 0) {
+            throw new IllegalArgumentException("key can not be empty");
+        }
+    }
+
+    @Override @Deprecated
     public double toNumber() {
         return inGlobal(new Callable<Double>() {
             @Override public Double call() {
@@ -791,4 +896,28 @@
             }
         });
     }
+
+    @Override
+    public Object getDefaultValue(final Class<?> hint) {
+        return inGlobal(new Callable<Object>() {
+            @Override public Object call() {
+                try {
+                    return sobj.getDefaultValue(hint);
+                } catch (final ECMAException e) {
+                    // We're catching ECMAException (likely TypeError), and translating it to
+                    // UnsupportedOperationException. This in turn will be translated into TypeError of the
+                    // caller's Global by JSType#toPrimitive(JSObject,Class) therefore ensuring that it's
+                    // recognized as "instanceof TypeError" in the caller.
+                    throw new UnsupportedOperationException(e.getMessage(), e);
+                }
+            }
+        });
+    }
+
+    private ScriptObjectMirror asJSONCompatible() {
+        if (this.jsonCompatible) {
+            return this;
+        }
+        return new ScriptObjectMirror(sobj, global, true);
+    }
 }
diff --git a/src/jdk/nashorn/api/scripting/ScriptUtils.java b/src/jdk/nashorn/api/scripting/ScriptUtils.java
index b6c4c97..0d5d676 100644
--- a/src/jdk/nashorn/api/scripting/ScriptUtils.java
+++ b/src/jdk/nashorn/api/scripting/ScriptUtils.java
@@ -38,7 +38,10 @@
 
 /**
  * Utilities that are to be called from script code.
+ *
+ * @since 1.8u40
  */
+@jdk.Exported
 public final class ScriptUtils {
     private ScriptUtils() {}
 
@@ -76,7 +79,7 @@
      * @return a synchronizing wrapper function
      */
     public static Object makeSynchronizedFunction(final ScriptFunction func, final Object sync) {
-        return func.makeSynchronizedFunction(unwrap(sync));
+        return func.createSynchronized(unwrap(sync));
     }
 
     /**
diff --git a/src/jdk/nashorn/api/scripting/URLReader.java b/src/jdk/nashorn/api/scripting/URLReader.java
index 53efeee..85a585c 100644
--- a/src/jdk/nashorn/api/scripting/URLReader.java
+++ b/src/jdk/nashorn/api/scripting/URLReader.java
@@ -30,12 +30,16 @@
 import java.io.Reader;
 import java.net.URL;
 import java.nio.charset.Charset;
+import java.util.Objects;
 import jdk.nashorn.internal.runtime.Source;
 
 /**
  * A Reader that reads from a URL. Used to make sure that the reader
  * reads content from given URL and can be trusted to do so.
+ *
+ * @since 1.8u40
  */
+@jdk.Exported
 public final class URLReader extends Reader {
     // underlying URL
     private final URL url;
@@ -74,9 +78,7 @@
      * @throws NullPointerException if url is null
      */
     public URLReader(final URL url, final Charset cs) {
-        // null check
-        url.getClass();
-        this.url = url;
+        this.url = Objects.requireNonNull(url);
         this.cs  = cs;
     }
 
@@ -101,7 +103,7 @@
     /**
      * Charset used by this reader
      *
-     * @return the Chartset used to convert bytes to chars
+     * @return the Charset used to convert bytes to chars
      */
     public Charset getCharset() {
         return cs;
diff --git a/src/jdk/nashorn/api/scripting/package-info.java b/src/jdk/nashorn/api/scripting/package-info.java
index f017ba9..1890924 100644
--- a/src/jdk/nashorn/api/scripting/package-info.java
+++ b/src/jdk/nashorn/api/scripting/package-info.java
@@ -35,5 +35,8 @@
  * interfaces, allowing for efficient pre-compilation and repeated execution of scripts. In addition,
  * this package provides nashorn specific extension classes, interfaces and methods. See
  * {@link jdk.nashorn.api.scripting.NashornScriptEngineFactory} for further details.
+ *
+ * @since 1.8u40
  */
+@jdk.Exported
 package jdk.nashorn.api.scripting;
diff --git a/src/jdk/nashorn/internal/codegen/ApplySpecialization.java b/src/jdk/nashorn/internal/codegen/ApplySpecialization.java
index 62e58f4..51abacd 100644
--- a/src/jdk/nashorn/internal/codegen/ApplySpecialization.java
+++ b/src/jdk/nashorn/internal/codegen/ApplySpecialization.java
@@ -40,11 +40,9 @@
 import jdk.nashorn.internal.ir.CallNode;
 import jdk.nashorn.internal.ir.Expression;
 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.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
@@ -82,7 +80,7 @@
  */
 
 @Logger(name="apply2call")
-public final class ApplySpecialization extends NodeVisitor<LexicalContext> implements Loggable {
+public final class ApplySpecialization extends SimpleNodeVisitor implements Loggable {
 
     private static final boolean USE_APPLY2CALL = Options.getBooleanProperty("nashorn.apply2call", true);
 
@@ -106,7 +104,6 @@
      * @param compiler compiler
      */
     public ApplySpecialization(final Compiler compiler) {
-        super(new LexicalContext());
         this.compiler = compiler;
         this.log = initLogger(compiler.getContext());
     }
@@ -139,7 +136,7 @@
 
     private boolean hasApplies(final FunctionNode functionNode) {
         try {
-            functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+            functionNode.accept(new SimpleNodeVisitor() {
                 @Override
                 public boolean enterFunctionNode(final FunctionNode fn) {
                     return fn == functionNode;
@@ -173,7 +170,7 @@
         final Deque<Set<Expression>> stack = new ArrayDeque<>();
 
         //ensure that arguments is only passed as arg to apply
-        functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        functionNode.accept(new SimpleNodeVisitor() {
 
             private boolean isCurrentArg(final Expression expr) {
                 return !stack.isEmpty() && stack.peek().contains(expr); //args to current apply call
@@ -283,17 +280,13 @@
             start++;
         }
 
-        start++; //we always uses this
+        start++; // we always use this
 
-        final List<IdentNode> params    = functionNode.getParameters();
+        assert functionNode.getNumOfParams() == 0 : "apply2call on function with named paramaters!";
         final List<IdentNode> newParams = new ArrayList<>();
-        final long to = Math.max(params.size(), actualCallSiteType.parameterCount() - start);
+        final long to = 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));
-            }
+            newParams.add(new IdentNode(functionNode.getToken(), functionNode.getFinish(), EXPLODED_ARGUMENT_PREFIX.symbolName() + (i)));
         }
 
         callSiteTypes.push(actualCallSiteType);
@@ -302,7 +295,28 @@
 
     @Override
     public boolean enterFunctionNode(final FunctionNode functionNode) {
-        if (!USE_APPLY2CALL) {
+        // Cheap tests first
+        if (!(
+                // is the transform globally enabled?
+                USE_APPLY2CALL
+
+                // Are we compiling lazily? We can't known the number and types of the actual parameters at
+                // the caller when compiling eagerly, so this only works with on-demand compilation.
+                && compiler.isOnDemandCompilation()
+
+                // Does the function even reference the "arguments" identifier (without redefining it)? If not,
+                // it trivially can't have an expression of form "f.apply(self, arguments)" that this transform
+                // is targeting.
+                && functionNode.needsArguments()
+
+                // Does the function have eval? If so, it can arbitrarily modify arguments so we can't touch it.
+                && !functionNode.hasEval()
+
+                // Finally, does the function declare any parameters explicitly? We don't support that. It could
+                // be done, but has some complications. Therefore only a function with no explicit parameters
+                // is considered.
+                && functionNode.getNumOfParams() == 0))
+        {
             return false;
         }
 
@@ -312,14 +326,6 @@
             return false;
         }
 
-        if (!compiler.isOnDemandCompilation()) {
-            return false;
-        }
-
-        if (functionNode.hasEval()) {
-            return false;
-        }
-
         if (!hasApplies(functionNode)) {
             return false;
         }
@@ -375,7 +381,7 @@
         callSiteTypes.pop();
         explodedArguments.pop();
 
-        return newFunctionNode.setState(lc, CompilationState.BUILTINS_TRANSFORMED);
+        return newFunctionNode;
     }
 
     private static boolean isApply(final CallNode callNode) {
diff --git a/src/jdk/nashorn/internal/codegen/AssignSymbols.java b/src/jdk/nashorn/internal/codegen/AssignSymbols.java
index a4fb7bd..73ded48 100644
--- a/src/jdk/nashorn/internal/codegen/AssignSymbols.java
+++ b/src/jdk/nashorn/internal/codegen/AssignSymbols.java
@@ -65,17 +65,14 @@
 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.Splittable;
 import jdk.nashorn.internal.ir.Statement;
 import jdk.nashorn.internal.ir.SwitchNode;
 import jdk.nashorn.internal.ir.Symbol;
@@ -83,7 +80,8 @@
 import jdk.nashorn.internal.ir.UnaryNode;
 import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.WithNode;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
+import jdk.nashorn.internal.parser.TokenType;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ECMAErrors;
 import jdk.nashorn.internal.runtime.ErrorManager;
@@ -103,7 +101,7 @@
  * visitor.
  */
 @Logger(name="symbols")
-final class AssignSymbols extends NodeVisitor<LexicalContext> implements Loggable {
+final class AssignSymbols extends SimpleNodeVisitor implements Loggable {
     private final DebugLogger log;
     private final boolean     debug;
 
@@ -135,15 +133,11 @@
             functionNode.compilerConstant(SCOPE).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()) {
+        if(functionNode.isNamedFunctionExpression() && !functionNode.usesSelfSymbol()) {
             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();
+            if(selfSymbol != null && selfSymbol.isFunctionSelf()) {
+                selfSymbol.setNeedsSlot(false);
+                selfSymbol.clearFlag(Symbol.IS_VAR);
             }
         }
         return functionNode;
@@ -152,12 +146,13 @@
     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;
+    private final boolean isOnDemand;
 
     public AssignSymbols(final Compiler compiler) {
-        super(new LexicalContext());
         this.compiler = compiler;
         this.log   = initLogger(compiler.getContext());
         this.debug = log.isEnabled();
+        this.isOnDemand = compiler.isOnDemandCompilation();
     }
 
     @Override
@@ -190,7 +185,7 @@
      */
     private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
         // This visitor will assign symbol to all declared variables.
-        body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        body.accept(new SimpleNodeVisitor() {
             @Override
             protected boolean enterDefault(final Node node) {
                 // Don't bother visiting expressions; var is a statement, it can't be inside an expression.
@@ -245,7 +240,7 @@
 
     /**
      * 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
+     * used to create assignment 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
@@ -393,7 +388,7 @@
 
             // Create and add to appropriate block.
             symbol = createSymbol(name, flags);
-            symbolBlock.putSymbol(lc, symbol);
+            symbolBlock.putSymbol(symbol);
 
             if ((flags & IS_SCOPE) == 0) {
                 // Initial assumption; symbol can lose its slot later
@@ -443,7 +438,7 @@
         start(block);
 
         if (lc.isFunctionBody()) {
-            block.clearSymbols();
+            assert !block.hasSymbols();
             final FunctionNode fn = lc.getCurrentFunction();
             if (isUnparsedFunction(fn)) {
                 // It's a skipped nested function. Just mark the symbols being used by it as being in use.
@@ -462,7 +457,7 @@
     }
 
     private boolean isUnparsedFunction(final FunctionNode fn) {
-        return compiler.isOnDemandCompilation() && fn != lc.getOutermostFunction();
+        return isOnDemand && fn != lc.getOutermostFunction();
     }
 
     @Override
@@ -490,20 +485,31 @@
         final Block body = lc.getCurrentBlock();
 
         initFunctionWideVariables(functionNode, body);
+        acceptDeclarations(functionNode, body);
+        defineFunctionSelfSymbol(functionNode, body);
+    }
 
-        if (!functionNode.isProgram() && !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, functionNode, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE);
-            if(functionNode.allVarsInScope()) { // basically, has deep eval
-                lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL);
-            }
+    private void defineFunctionSelfSymbol(final FunctionNode functionNode, final Block body) {
+        // Function self-symbol is only declared as a local variable for named function expressions. Declared functions
+        // don't need it as they are local variables in their declaring scope.
+        if (!functionNode.isNamedFunctionExpression()) {
+            return;
         }
 
-        acceptDeclarations(functionNode, body);
+        final String name = functionNode.getIdent().getName();
+        assert name != null; // As it's a named function expression.
+
+        if (body.getExistingSymbol(name) != null) {
+            // Body already has a declaration for the name. It's either a parameter "function x(x)" or a
+            // top-level variable "function x() { ... var x; ... }".
+            return;
+        }
+
+        defineSymbol(body, name, functionNode, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE);
+        if(functionNode.allVarsInScope()) { // basically, has deep eval
+            // We must conservatively presume that eval'd code can dynamically use the function symbol.
+            lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL);
+        }
     }
 
     @Override
@@ -543,9 +549,7 @@
     private void defineVarIdent(final VarNode varNode) {
         final IdentNode ident = varNode.getName();
         final int flags;
-        if (varNode.isAnonymousFunctionDeclaration()) {
-            flags = IS_INTERNAL;
-        } else if (!varNode.isBlockScoped() && lc.getCurrentFunction().isProgram()) {
+        if (!varNode.isBlockScoped() && lc.getCurrentFunction().isProgram()) {
             flags = IS_SCOPE;
         } else {
             flags = 0;
@@ -705,25 +709,12 @@
         return definingFn == function;
     }
 
-    private void checkConstAssignment(final IdentNode ident) {
-        // Check for reassignment of constant
-        final Symbol symbol = ident.getSymbol();
-        if (symbol.isConst()) {
-            throwParserException(ECMAErrors.getMessage("syntax.error.assign.constant", symbol.getName()), ident);
-        }
-    }
-
     @Override
     public Node leaveBinaryNode(final BinaryNode binaryNode) {
-        if (binaryNode.isAssignment() && binaryNode.lhs() instanceof IdentNode) {
-            checkConstAssignment((IdentNode) binaryNode.lhs());
-        }
-        switch (binaryNode.tokenType()) {
-        case ASSIGN:
+        if (binaryNode.isTokenType(TokenType.ASSIGN)) {
             return leaveASSIGN(binaryNode);
-        default:
-            return super.leaveBinaryNode(binaryNode);
         }
+        return super.leaveBinaryNode(binaryNode);
     }
 
     private Node leaveASSIGN(final BinaryNode binaryNode) {
@@ -744,9 +735,6 @@
 
     @Override
     public Node leaveUnaryNode(final UnaryNode unaryNode) {
-        if (unaryNode.isAssignment() && unaryNode.getExpression() instanceof IdentNode) {
-            checkConstAssignment((IdentNode) unaryNode.getExpression());
-        }
         switch (unaryNode.tokenType()) {
         case DELETE:
             return leaveDELETE(unaryNode);
@@ -757,28 +745,6 @@
         }
     }
 
-    @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()) {
-            // OTOH, we must not declare symbols from nested functions to be locals. As we're doing on-demand
-            // compilation, and we're skipping parsing the function bodies for nested functions, this
-            // basically only means their parameters. It'd be enough to mistakenly declare to be a local a
-            // symbol in the outer function named the same as one of the parameters, though.
-            if (lc.getFunction(block) == lc.getOutermostFunction()) {
-                for (final Symbol symbol: block.getSymbols()) {
-                    if (!symbol.isScope()) {
-                        assert symbol.isVar() || symbol.isParam();
-                        compiler.declareLocalSymbol(symbol.getName());
-                    }
-                }
-            }
-        }
-        return block;
-    }
-
     private Node leaveDELETE(final UnaryNode unaryNode) {
         final FunctionNode currentFunctionNode = lc.getCurrentFunction();
         final boolean      strictMode          = currentFunctionNode.isStrict();
@@ -793,12 +759,13 @@
             // 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);
+            if (symbol.isThis()) {
+                // Can't delete "this", ignore and return true
+                return LiteralNode.newInstance(unaryNode, true);
             }
-            final Expression literalNode = (Expression)LiteralNode.newInstance(unaryNode, name).accept(this);
+            final Expression literalNode = LiteralNode.newInstance(unaryNode, name);
+            final boolean failDelete = strictMode || (!symbol.isScope() && (symbol.isParam() || (symbol.isVar() && !symbol.isProgramLevel())));
 
             if (!failDelete) {
                 args.add(compilerConstantIdentifier(SCOPE));
@@ -808,13 +775,15 @@
 
             if (failDelete) {
                 request = Request.FAIL_DELETE;
+            } else if ((symbol.isGlobal() && !symbol.isFunctionDeclaration()) || symbol.isProgramLevel()) {
+                request = Request.SLOW_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(LiteralNode.newInstance(unaryNode, property));
             args.add(strictFlagNode);
 
         } else if (rhs instanceof IndexNode) {
@@ -827,15 +796,15 @@
             args.add(strictFlagNode);
 
         } else {
-            return LiteralNode.newInstance(unaryNode, true).accept(this);
+            return LiteralNode.newInstance(unaryNode, true);
         }
-        return new RuntimeNode(unaryNode, request, args).accept(this);
+        return new RuntimeNode(unaryNode, request, args);
     }
 
     @Override
     public Node leaveForNode(final ForNode forNode) {
         if (forNode.isForIn()) {
-            forNode.setIterator(newObjectInternal(ITERATOR_PREFIX)); //NASHORN-73
+            return forNode.setIterator(lc, newObjectInternal(ITERATOR_PREFIX)); //NASHORN-73
         }
 
         return end(forNode);
@@ -855,7 +824,7 @@
                        lc.applyTopFlags(functionNode))))
                        .setThisProperties(lc, thisProperties.pop().size()));
         }
-        return finalizedFunction.setState(lc, CompilationState.SYMBOLS_ASSIGNED);
+        return finalizedFunction;
     }
 
     @Override
@@ -911,21 +880,18 @@
     public Node leaveSwitchNode(final SwitchNode switchNode) {
         // We only need a symbol for the tag if it's not an integer switch node
         if(!switchNode.isUniqueInteger()) {
-            switchNode.setTag(newObjectInternal(SWITCH_TAG_PREFIX));
+            return switchNode.setTag(lc, newObjectInternal(SWITCH_TAG_PREFIX));
         }
         return switchNode;
     }
 
     @Override
     public Node leaveTryNode(final TryNode tryNode) {
-        tryNode.setException(exceptionSymbol());
-        if (tryNode.getFinallyBody() != null) {
-            tryNode.setFinallyCatchAll(exceptionSymbol());
-        }
+        assert tryNode.getFinallyBody() == null;
 
         end(tryNode);
 
-        return tryNode;
+        return tryNode.setException(lc, exceptionSymbol());
     }
 
     private Node leaveTYPEOF(final UnaryNode unaryNode) {
@@ -934,13 +900,13 @@
         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
+            args.add(LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName())); //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'
+            args.add(LiteralNode.newInstance(unaryNode)); //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);
+        final Node runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args);
 
         end(unaryNode);
 
@@ -948,7 +914,7 @@
     }
 
     private FunctionNode markProgramBlock(final FunctionNode functionNode) {
-        if (compiler.isOnDemandCompilation() || !functionNode.isProgram()) {
+        if (isOnDemand || !functionNode.isProgram()) {
             return functionNode;
         }
 
@@ -1015,7 +981,7 @@
         boolean previousWasBlock = false;
         for (final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
             final LexicalContextNode node = it.next();
-            if (node instanceof FunctionNode || isSplitArray(node)) {
+            if (node instanceof FunctionNode || isSplitLiteral(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;
@@ -1041,12 +1007,8 @@
         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());
+    private static boolean isSplitLiteral(final LexicalContextNode expr) {
+        return expr instanceof Splittable && ((Splittable) expr).getSplitRanges() != null;
     }
 
     private void throwUnprotectedSwitchError(final VarNode varNode) {
diff --git a/src/jdk/nashorn/internal/codegen/BranchOptimizer.java b/src/jdk/nashorn/internal/codegen/BranchOptimizer.java
index 5c8f964..99862fe 100644
--- a/src/jdk/nashorn/internal/codegen/BranchOptimizer.java
+++ b/src/jdk/nashorn/internal/codegen/BranchOptimizer.java
@@ -31,6 +31,7 @@
 import static jdk.nashorn.internal.codegen.Condition.LE;
 import static jdk.nashorn.internal.codegen.Condition.LT;
 import static jdk.nashorn.internal.codegen.Condition.NE;
+import static jdk.nashorn.internal.parser.TokenType.NOT;
 
 import jdk.nashorn.internal.ir.BinaryNode;
 import jdk.nashorn.internal.ir.Expression;
@@ -57,21 +58,11 @@
     }
 
     private void branchOptimizer(final UnaryNode unaryNode, final Label label, final boolean state) {
-        final Expression rhs = unaryNode.getExpression();
-
-        switch (unaryNode.tokenType()) {
-        case NOT:
-            branchOptimizer(rhs, label, !state);
-            return;
-        default:
-            if (unaryNode.getType().isBoolean()) {
-                branchOptimizer(rhs, label, state);
-                return;
-            }
-            break;
+        if (unaryNode.isTokenType(NOT)) {
+            branchOptimizer(unaryNode.getExpression(), label, !state);
+        } else {
+            loadTestAndJump(unaryNode, label, state);
         }
-
-        loadTestAndJump(unaryNode, label, state);
     }
 
     private void branchOptimizer(final BinaryNode binaryNode, final Label label, final boolean state) {
@@ -105,33 +96,33 @@
 
         case EQ:
         case EQ_STRICT:
-            codegen.loadBinaryOperands(binaryNode);
+            codegen.loadComparisonOperands(binaryNode);
             method.conditionalJump(state ? EQ : NE, true, label);
             return;
 
         case NE:
         case NE_STRICT:
-            codegen.loadBinaryOperands(binaryNode);
+            codegen.loadComparisonOperands(binaryNode);
             method.conditionalJump(state ? NE : EQ, true, label);
             return;
 
         case GE:
-            codegen.loadBinaryOperands(binaryNode);
+            codegen.loadComparisonOperands(binaryNode);
             method.conditionalJump(state ? GE : LT, false, label);
             return;
 
         case GT:
-            codegen.loadBinaryOperands(binaryNode);
+            codegen.loadComparisonOperands(binaryNode);
             method.conditionalJump(state ? GT : LE, false, label);
             return;
 
         case LE:
-            codegen.loadBinaryOperands(binaryNode);
+            codegen.loadComparisonOperands(binaryNode);
             method.conditionalJump(state ? LE : GT, true, label);
             return;
 
         case LT:
-            codegen.loadBinaryOperands(binaryNode);
+            codegen.loadComparisonOperands(binaryNode);
             method.conditionalJump(state ? LT : GE, true, label);
             return;
 
diff --git a/src/jdk/nashorn/internal/codegen/CacheAst.java b/src/jdk/nashorn/internal/codegen/CacheAst.java
new file mode 100644
index 0000000..6f66ea3
--- /dev/null
+++ b/src/jdk/nashorn/internal/codegen/CacheAst.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.ArrayDeque;
+import java.util.Collections;
+import java.util.Deque;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.Statement;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
+
+class CacheAst extends SimpleNodeVisitor {
+    private final Deque<RecompilableScriptFunctionData> dataStack = new ArrayDeque<>();
+
+    private final Compiler compiler;
+
+    CacheAst(final Compiler compiler) {
+        this.compiler = compiler;
+        assert !compiler.isOnDemandCompilation();
+    }
+
+    @Override
+    public boolean enterFunctionNode(final FunctionNode functionNode) {
+        final int id = functionNode.getId();
+        // It isn't necessary to keep a stack of RecompilableScriptFunctionData, but then we'd need to do a
+        // potentially transitive lookup with compiler.getScriptFunctionData(id) for deeper functions; this way
+        // we keep it constant time.
+        dataStack.push(dataStack.isEmpty() ? compiler.getScriptFunctionData(id) : dataStack.peek().getScriptFunctionData(id));
+        return true;
+    }
+
+    @Override
+    public Node leaveFunctionNode(final FunctionNode functionNode) {
+        final RecompilableScriptFunctionData data = dataStack.pop();
+        if (functionNode.isSplit()) {
+            // NOTE: cache only split function ASTs from eager pass. Caching non-split functions would require
+            // some additional work, namely creating the concept of "uncacheable" function and reworking
+            // ApplySpecialization to ensure that functions undergoing apply-to-call transformations are not
+            // cacheable as well as recomputing Symbol.useCount when caching the eagerly parsed AST.
+            // Recomputing Symbol.useCount would be needed so it will only reflect uses from within the
+            // function being cached (and not reflect uses from its own nested functions or functions it is
+            // nested in). This is consistent with the count an on-demand recompilation of the function would
+            // produce. This is important as the decision to emit shared scope calls is based on this count,
+            // and if it is not matched between a previous version of the code and its deoptimizing rest-of
+            // compilation, it can result in rest-of not emitting a shared scope call where a previous version
+            // of the code (compiled from a cached eager pre-pass seeing higher (global) useCount) would emit
+            // it, causing a mismatch in stack shapes between previous code and its rest-of.
+            data.setCachedAst(functionNode);
+        }
+
+        if (!dataStack.isEmpty() && ((dataStack.peek().getFunctionFlags() & FunctionNode.IS_SPLIT) != 0)) {
+            // Return a function node with no body so that caching outer functions doesn't hold on to nested
+            // functions' bodies. Note we're doing this only for functions directly nested inside split
+            // functions, since we're only caching the split ones. It is not necessary to limit body removal
+            // to just these functions, but it's a cheap way to prevent unnecessary AST mutations.
+            return functionNode.setBody(lc, functionNode.getBody().setStatements(null, Collections.<Statement>emptyList()));
+        }
+        return functionNode;
+    }
+}
diff --git a/src/jdk/nashorn/internal/codegen/ClassEmitter.java b/src/jdk/nashorn/internal/codegen/ClassEmitter.java
index 80bb61d..577504d 100644
--- a/src/jdk/nashorn/internal/codegen/ClassEmitter.java
+++ b/src/jdk/nashorn/internal/codegen/ClassEmitter.java
@@ -100,14 +100,10 @@
  * There is also a very nice debug interface that can emit formatted
  * bytecodes that have been written. This is enabled by setting the
  * environment "nashorn.codegen.debug" to true, or --log=codegen:{@literal <level>}
- * <p>
- * A ClassEmitter implements an Emitter - i.e. it needs to have
- * well defined start and end calls for whatever it is generating. Assertions
- * detect if this is not true
  *
  * @see Compiler
  */
-public class ClassEmitter implements Emitter {
+public class ClassEmitter {
     /** Default flags for class generation - public class */
     private static final EnumSet<Flag> DEFAULT_METHOD_FLAGS = EnumSet.of(Flag.PUBLIC);
 
@@ -147,7 +143,7 @@
 
     /**
      * Constructor - only used internally in this class as it breaks
-     * abstraction towards ASM or other code generator below
+     * abstraction towards ASM or other code generator below.
      *
      * @param env script environment
      * @param cw  ASM classwriter
@@ -160,7 +156,8 @@
     }
 
     /**
-     * Return the method names encountered
+     * Return the method names encountered.
+     *
      * @return method names
      */
     public Set<String> getMethodNames() {
@@ -168,12 +165,13 @@
     }
 
     /**
-     * Constructor
+     * Constructor.
      *
      * @param env             script environment
      * @param className       name of class to weave
      * @param superClassName  super class name for class
-     * @param interfaceNames  names of interfaces implemented by this class, or null if none
+     * @param interfaceNames  names of interfaces implemented by this class, or
+     *        {@code null} if none
      */
     ClassEmitter(final Context context, final String className, final String superClassName, final String... interfaceNames) {
         this(context, new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS));
@@ -181,7 +179,7 @@
     }
 
     /**
-     * Constructor from the compiler
+     * Constructor from the compiler.
      *
      * @param env           Script environment
      * @param sourceName    Source name
@@ -220,7 +218,6 @@
     }
 
     /**
-     * Returns the name of the compile unit class name.
      * @return the name of the compile unit class name.
      */
     String getUnitClassName() {
@@ -228,7 +225,8 @@
     }
 
     /**
-     * Get the method count, including init and clinit methods
+     * Get the method count, including init and clinit methods.
+     *
      * @return method count
      */
     public int getMethodCount() {
@@ -236,7 +234,8 @@
     }
 
     /**
-     * Get the clinit count
+     * Get the clinit count.
+     *
      * @return clinit count
      */
     public int getClinitCount() {
@@ -244,7 +243,8 @@
     }
 
     /**
-     * Get the init count
+     * Get the init count.
+     *
      * @return init count
      */
     public int getInitCount() {
@@ -252,7 +252,8 @@
     }
 
     /**
-     * Get the field count
+     * Get the field count.
+     *
      * @return field count
      */
     public int getFieldCount() {
@@ -263,6 +264,7 @@
      * Convert a binary name to a package/class name.
      *
      * @param name Binary name.
+     *
      * @return Package/class name.
      */
     private static String pathName(final String name) {
@@ -271,6 +273,7 @@
 
     /**
      * Define the static fields common in all scripts.
+     *
      * @param strictMode Should we generate this method in strict mode
      */
     private void defineCommonStatics(final boolean strictMode) {
@@ -287,8 +290,8 @@
     }
 
     /**
-     * Define static utilities common needed in scripts.  These are per compile unit
-     * and therefore have to be defined here and not in code gen.
+     * Define static utilities common needed in scripts. These are per compile
+     * unit and therefore have to be defined here and not in code gen.
      */
     private void defineCommonUtilities() {
         assert unitClassName != null;
@@ -336,7 +339,9 @@
     }
 
     /**
-     * Constructs a primitive specific method for getting the ith entry from the constants table as an array.
+     * 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<?> clazz) {
@@ -359,7 +364,9 @@
 
     /**
      * Generate the name of a get array from constant pool method.
+     *
      * @param clazz Name of array class.
+     *
      * @return Method name.
      */
     static String getArrayMethodName(final Class<?> clazz) {
@@ -369,6 +376,7 @@
 
     /**
      * Ensure a get constant method is issued for the class.
+     *
      * @param clazz Class of constant.
      */
     void needGetConstantMethod(final Class<?> clazz) {
@@ -376,12 +384,12 @@
     }
 
     /**
-     * Inspect class name and decide whether we are generating a ScriptObject class
+     * Inspect class name and decide whether we are generating a ScriptObject class.
      *
      * @param scriptPrefix the script class prefix for the current script
      * @param type         the type to check
      *
-     * @return true if type is ScriptObject
+     * @return {@code true} if type is ScriptObject
      */
     private static boolean isScriptObject(final String scriptPrefix, final String type) {
         if (type.startsWith(scriptPrefix)) {
@@ -396,19 +404,15 @@
     }
 
     /**
-     * Call at beginning of class emission
-     * @see Emitter
+     * Call at beginning of class emission.
      */
-    @Override
     public void begin() {
         classStarted = true;
     }
 
     /**
-     * Call at end of class emission
-     * @see Emitter
+     * Call at end of class emission.
      */
-    @Override
     public void end() {
         assert classStarted : "class not started for " + unitClassName;
 
@@ -431,7 +435,9 @@
 
     /**
      * Disassemble an array of byte code.
+     *
      * @param bytecode  byte array representing bytecode
+     *
      * @return disassembly as human readable string
      */
     static String disassemble(final byte[] bytecode) {
@@ -453,7 +459,7 @@
     }
 
     /**
-     * Call back from MethodEmitter for method start
+     * Call back from MethodEmitter for method start.
      *
      * @see MethodEmitter
      *
@@ -465,7 +471,7 @@
     }
 
     /**
-     * Call back from MethodEmitter for method end
+     * Call back from MethodEmitter for method end.
      *
      * @see MethodEmitter
      *
@@ -477,7 +483,7 @@
     }
 
     /**
-     * Add a new method to the class - defaults to public method
+     * Add a new method to the class - defaults to public method.
      *
      * @param methodName name of method
      * @param rtype      return type of the method
@@ -490,7 +496,7 @@
     }
 
     /**
-     * Add a new method to the class - defaults to public method
+     * Add a new method to the class - defaults to public method.
      *
      * @param methodFlags access flags for the method
      * @param methodName  name of method
@@ -506,7 +512,7 @@
     }
 
     /**
-     * Add a new method to the class - defaults to public method
+     * Add a new method to the class - defaults to public method.
      *
      * @param methodName name of method
      * @param descriptor descriptor of method
@@ -518,7 +524,7 @@
     }
 
     /**
-     * Add a new method to the class - defaults to public method
+     * Add a new method to the class - defaults to public method.
      *
      * @param methodFlags access flags for the method
      * @param methodName  name of method
@@ -533,9 +539,10 @@
     }
 
     /**
-     * Add a new method to the class, representing a function node
+     * Add a new method to the class, representing a function node.
      *
      * @param functionNode the function node to generate a method for
+     *
      * @return method emitter to use for weaving this method
      */
     MethodEmitter method(final FunctionNode functionNode) {
@@ -553,9 +560,11 @@
     }
 
     /**
-     * Add a new method to the class, representing a rest-of version of the function node
+     * 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) {
@@ -573,7 +582,7 @@
 
 
     /**
-     * Start generating the <clinit> method in the class
+     * Start generating the <clinit> method in the class.
      *
      * @return method emitter to use for weaving <clinit>
      */
@@ -583,7 +592,7 @@
     }
 
     /**
-     * Start generating an <init>()V method in the class
+     * Start generating an <init>()V method in the class.
      *
      * @return method emitter to use for weaving <init>()V
      */
@@ -593,7 +602,7 @@
     }
 
     /**
-     * Start generating an <init>()V method in the class
+     * Start generating an <init>()V method in the class.
      *
      * @param ptypes parameter types for constructor
      * @return method emitter to use for weaving <init>()V
@@ -604,7 +613,7 @@
     }
 
     /**
-     * Start generating an <init>(...)V method in the class
+     * Start generating an <init>(...)V method in the class.
      *
      * @param flags  access flags for the constructor
      * @param ptypes parameter types for the constructor
@@ -617,7 +626,7 @@
     }
 
     /**
-     * Add a field to the class, initialized to a value
+     * Add a field to the class, initialized to a value.
      *
      * @param fieldFlags flags, e.g. should it be static or public etc
      * @param fieldName  name of field
@@ -632,7 +641,7 @@
     }
 
     /**
-     * Add a field to the class
+     * Add a field to the class.
      *
      * @param fieldFlags access flags for the field
      * @param fieldName  name of field
@@ -645,7 +654,7 @@
     }
 
     /**
-     * Add a field to the class - defaults to public
+     * Add a field to the class - defaults to public.
      *
      * @param fieldName  name of field
      * @param fieldType  type of field
@@ -658,7 +667,8 @@
      * Return a bytecode array from this ClassEmitter. The ClassEmitter must
      * have been ended (having its end function called) for this to work.
      *
-     * @return byte code array for generated class, null if class generation hasn't been ended with {@link ClassEmitter#end()}
+     * @return byte code array for generated class, {@code null} if class
+     *         generation hasn't been ended with {@link ClassEmitter#end()}.
      */
     byte[] toByteArray() {
         assert classEnded;
@@ -670,13 +680,9 @@
     }
 
     /**
-     * Abstraction for flags used in class emission
-     *
-     * We provide abstraction separating these from the underlying bytecode
-     * emitter.
-     *
-     * Flags are provided for method handles, protection levels, static/virtual
-     * fields/methods.
+     * Abstraction for flags used in class emission. We provide abstraction
+     * separating these from the underlying bytecode emitter. Flags are provided
+     * for method handles, protection levels, static/virtual fields/methods.
      */
     static enum Flag {
         /** method handle with static access */
@@ -714,10 +720,12 @@
         }
 
         /**
-         * Return the corresponding ASM flag value for an enum set of flags
+         * Return the corresponding ASM flag value for an enum set of flags.
          *
          * @param flags enum set of flags
-         * @return an integer value representing the flags intrinsic values or:ed together
+         *
+         * @return an integer value representing the flags intrinsic values
+         *         or:ed together
          */
         static int getValue(final EnumSet<Flag> flags) {
             int v = 0;
diff --git a/src/jdk/nashorn/internal/codegen/CodeGenerator.java b/src/jdk/nashorn/internal/codegen/CodeGenerator.java
index 59aa258..1f6aaad 100644
--- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java
+++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java
@@ -38,13 +38,11 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.SPLIT_PREFIX;
 import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
 import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
-import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup;
 import static jdk.nashorn.internal.codegen.CompilerConstants.interfaceCallNoLookup;
 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 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.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
@@ -86,7 +84,6 @@
 import jdk.nashorn.internal.ir.Block;
 import jdk.nashorn.internal.ir.BlockStatement;
 import jdk.nashorn.internal.ir.BreakNode;
-import jdk.nashorn.internal.ir.BreakableNode;
 import jdk.nashorn.internal.ir.CallNode;
 import jdk.nashorn.internal.ir.CaseNode;
 import jdk.nashorn.internal.ir.CatchNode;
@@ -96,19 +93,18 @@
 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.GetSplitState;
 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.JumpStatement;
+import jdk.nashorn.internal.ir.JumpToInlinedFinally;
 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;
@@ -121,6 +117,7 @@
 import jdk.nashorn.internal.ir.RuntimeNode.Request;
 import jdk.nashorn.internal.ir.SetSplitState;
 import jdk.nashorn.internal.ir.SplitReturn;
+import jdk.nashorn.internal.ir.Splittable;
 import jdk.nashorn.internal.ir.Statement;
 import jdk.nashorn.internal.ir.SwitchNode;
 import jdk.nashorn.internal.ir.Symbol;
@@ -132,9 +129,8 @@
 import jdk.nashorn.internal.ir.WhileNode;
 import jdk.nashorn.internal.ir.WithNode;
 import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.objects.Global;
-import jdk.nashorn.internal.objects.ScriptFunctionImpl;
 import jdk.nashorn.internal.parser.Lexer.RegexToken;
 import jdk.nashorn.internal.parser.TokenType;
 import jdk.nashorn.internal.runtime.Context;
@@ -176,8 +172,7 @@
  * This quickly became apparent when the code generator was generalized to work
  * with all types, and not just numbers or objects.
  * <p>
- * The CodeGenerator visits nodes only once, tags them as resolved and emits
- * bytecode for them.
+ * The CodeGenerator visits nodes only once and emits bytecode for them.
  */
 @Logger(name="codegen")
 final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContext> implements Loggable {
@@ -186,9 +181,6 @@
 
     private static final String GLOBAL_OBJECT = Type.getInternalName(Global.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,
@@ -201,6 +193,17 @@
     private static final Call ENSURE_NUMBER = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
             "ensureNumber", double.class, Object.class, int.class);
 
+    private static final Call CREATE_FUNCTION_OBJECT = CompilerConstants.staticCallNoLookup(ScriptFunction.class,
+            "create", ScriptFunction.class, Object[].class, int.class, ScriptObject.class);
+    private static final Call CREATE_FUNCTION_OBJECT_NO_SCOPE = CompilerConstants.staticCallNoLookup(ScriptFunction.class,
+            "create", ScriptFunction.class, Object[].class, int.class);
+
+    private static final Call TO_NUMBER_FOR_EQ = CompilerConstants.staticCallNoLookup(JSType.class,
+            "toNumberForEq", double.class, Object.class);
+    private static final Call TO_NUMBER_FOR_STRICT_EQ = CompilerConstants.staticCallNoLookup(JSType.class,
+            "toNumberForStrictEq", double.class, Object.class);
+
+
     private static final Class<?> ITERATOR_CLASS = Iterator.class;
     static {
         assert ITERATOR_CLASS == CompilerConstants.ITERATOR_PREFIX.type();
@@ -239,12 +242,12 @@
     private final DebugLogger log;
 
     /** From what size should we use spill instead of fields for JavaScript objects? */
-    private static final int OBJECT_SPILL_THRESHOLD = Options.getIntProperty("nashorn.spill.threshold", 256);
+    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 ContinuationInfo continuationInfo;
 
     private final Deque<Label> scopeEntryLabels = new ArrayDeque<>();
 
@@ -291,6 +294,20 @@
     }
 
     /**
+     * Gets the flags for a scope call site.
+     * @param symbol a scope symbol
+     * @return the correct flags for the scope call site
+     */
+    private int getScopeCallSiteFlags(final Symbol symbol) {
+        assert symbol.isScope();
+        final int flags = getCallSiteFlags() | CALLSITE_SCOPE;
+        if (isEvalCode() && symbol.isGlobal()) {
+            return flags; // Don't set fast-scope flag on non-declared globals in eval code - see JDK-8077955.
+        }
+        return isFastScope(symbol) ? flags | CALLSITE_FAST_SCOPE : flags;
+    }
+
+    /**
      * Are we generating code for 'eval' code?
      * @return true if currently compiled code is 'eval' code.
      */
@@ -299,6 +316,14 @@
     }
 
     /**
+     * Are we using dual primitive/object field representation?
+     * @return true if using dual field representation, false for object-only fields
+     */
+    boolean useDualFields() {
+        return compiler.getContext().useDualFields();
+    }
+
+    /**
      * Load an identity node
      *
      * @param identNode an identity node to load
@@ -319,14 +344,23 @@
         }
 
         assert identNode.getSymbol().isScope() : identNode + " is not in scope!";
-        final int flags = CALLSITE_SCOPE | getCallSiteFlags();
+        final int flags = getScopeCallSiteFlags(symbol);
         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
+            if (symbol.getUseCount() > SharedScopeCall.FAST_SCOPE_GET_THRESHOLD && !identNode.isOptimistic()) {
+                // As shared scope vars are only used with non-optimistic identifiers, we switch from using TypeBounds to
                 // just a single definitive type, resultBounds.widest.
-                loadSharedScopeVar(resultBounds.widest, symbol, flags);
+                new OptimisticOperation(identNode, TypeBounds.OBJECT) {
+                    @Override
+                    void loadStack() {
+                        method.loadCompilerConstant(SCOPE);
+                    }
+
+                    @Override
+                    void consumeStack() {
+                        loadSharedScopeVar(resultBounds.widest, symbol, flags);
+                    }
+                }.emit();
             } else {
                 new LoadFastScopeVar(identNode, resultBounds, flags).emit();
             }
@@ -342,8 +376,14 @@
     // This is called the temporal dead zone (TDZ). See https://gist.github.com/rwaldron/f0807a758aa03bcdd58a
     private void checkTemporalDeadZone(final IdentNode identNode) {
         if (identNode.isDead()) {
-            method.load(identNode.getSymbol().getName());
-            method.invoke(ScriptRuntime.THROW_REFERENCE_ERROR);
+            method.load(identNode.getSymbol().getName()).invoke(ScriptRuntime.THROW_REFERENCE_ERROR);
+        }
+    }
+
+    // Runtime check for assignment to ES6 const
+    private void checkAssignTarget(final Expression expression) {
+        if (expression instanceof IdentNode && ((IdentNode)expression).getSymbol().isConst()) {
+            method.load(((IdentNode)expression).getSymbol().getName()).invoke(ScriptRuntime.THROW_CONST_TYPE_ERROR);
         }
     }
 
@@ -351,10 +391,6 @@
         return continuationEntryPoints != null;
     }
 
-    private boolean isOptimisticOrRestOf() {
-        return useOptimisticTypes() || isRestOf();
-    }
-
     private boolean isCurrentContinuationEntryPoint(final int programPoint) {
         return isRestOf() && getCurrentContinuationEntryPoint() == programPoint;
     }
@@ -431,13 +467,9 @@
     }
 
     private MethodEmitter loadSharedScopeVar(final Type valueType, final Symbol symbol, final int flags) {
-        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);
+        assert isFastScope(symbol);
+        method.load(getScopeProtoDepth(lc.getCurrentBlock(), symbol));
+        return lc.getScopeGet(unit, symbol, valueType, flags).generateInvoke(method);
     }
 
     private class LoadScopeVar extends OptimisticOperation {
@@ -475,7 +507,7 @@
 
     private class LoadFastScopeVar extends LoadScopeVar {
         LoadFastScopeVar(final IdentNode identNode, final TypeBounds resultBounds, final int flags) {
-            super(identNode, resultBounds, flags | CALLSITE_FAST_SCOPE);
+            super(identNode, resultBounds, flags);
         }
 
         @Override
@@ -486,7 +518,7 @@
 
     private MethodEmitter storeFastScopeVar(final Symbol symbol, final int flags) {
         loadFastScopeProto(symbol, true);
-        method.dynamicSet(symbol.getName(), flags | CALLSITE_FAST_SCOPE, false);
+        method.dynamicSet(symbol.getName(), flags, false);
         return method;
     }
 
@@ -611,6 +643,104 @@
         return method;
     }
 
+    /**
+     * Similar to {@link #loadBinaryOperands(BinaryNode)} but used specifically for loading operands of
+     * relational and equality comparison operators where at least one argument is non-object. (When both
+     * arguments are objects, we use {@link ScriptRuntime#EQ(Object, Object)}, {@link ScriptRuntime#LT(Object, Object)}
+     * etc. methods instead. Additionally, {@code ScriptRuntime} methods are used for strict (in)equality comparison
+     * of a boolean to anything that isn't a boolean.) This method handles the special case where one argument
+     * is an object and another is a primitive. Naively, these could also be delegated to {@code ScriptRuntime} methods
+     * by boxing the primitive. However, in all such cases the comparison is performed on numeric values, so it is
+     * possible to strength-reduce the operation by taking the number value of the object argument instead and
+     * comparing that to the primitive value ("primitive" will always be int, long, double, or boolean, and booleans
+     * compare as ints in these cases, so they're essentially numbers too). This method will emit code for loading
+     * arguments for such strength-reduced comparison. When both arguments are primitives, it just delegates to
+     * {@link #loadBinaryOperands(BinaryNode)}.
+     *
+     * @param cmp the comparison operation for which the operands need to be loaded on stack.
+     * @return the current method emitter.
+     */
+    MethodEmitter loadComparisonOperands(final BinaryNode cmp) {
+        final Expression lhs = cmp.lhs();
+        final Expression rhs = cmp.rhs();
+        final Type lhsType = lhs.getType();
+        final Type rhsType = rhs.getType();
+
+        // Only used when not both are object, for that we have ScriptRuntime.LT etc.
+        assert !(lhsType.isObject() && rhsType.isObject());
+
+        if (lhsType.isObject() || rhsType.isObject()) {
+            // We can reorder CONVERT LEFT and LOAD RIGHT only if either the left is a primitive, or the right
+            // is a local. This is more strict than loadBinaryNode reorder criteria, as it can allow JS primitive
+            // types too (notably: String is a JS primitive, but not a JVM primitive). We disallow String otherwise
+            // we would prematurely convert it to number when comparing to an optimistic expression, e.g. in
+            // "Hello" === String("Hello") the RHS starts out as an optimistic-int function call. If we allowed
+            // reordering, we'd end up with ToNumber("Hello") === {I%}String("Hello") that is obviously incorrect.
+            final boolean canReorder = lhsType.isPrimitive() || rhs.isLocal();
+            // If reordering is allowed, and we're using a relational operator (that is, <, <=, >, >=) and not an
+            // (in)equality operator, then we encourage combining of LOAD and CONVERT into a single operation.
+            // This is because relational operators' semantics prescribes vanilla ToNumber() conversion, while
+            // (in)equality operators need the specialized JSType.toNumberFor[Strict]Equals. E.g. in the code snippet
+            // "i < obj.size" (where i is primitive and obj.size is statically an object), ".size" will thus be allowed
+            // to compile as:
+            //   invokedynamic dyn:getProp|getElem|getMethod:size(Object;)D
+            // instead of the more costly:
+            //   invokedynamic dyn:getProp|getElem|getMethod:size(Object;)Object
+            //   invokestatic JSType.toNumber(Object)D
+            // Note also that even if this is allowed, we're only using it on operands that are non-optimistic, as
+            // otherwise the logic for determining effective optimistic-ness would turn an optimistic double return
+            // into a freely coercible one, which would be wrong.
+            final boolean canCombineLoadAndConvert = canReorder && cmp.isRelational();
+
+            // LOAD LEFT
+            loadExpression(lhs, canCombineLoadAndConvert && !lhs.isOptimistic() ? TypeBounds.NUMBER : TypeBounds.UNBOUNDED);
+
+            final Type lhsLoadedType = method.peekType();
+            final TokenType tt = cmp.tokenType();
+            if (canReorder) {
+                // Can reorder CONVERT LEFT and LOAD RIGHT
+                emitObjectToNumberComparisonConversion(method, tt);
+                loadExpression(rhs, canCombineLoadAndConvert && !rhs.isOptimistic() ? TypeBounds.NUMBER : TypeBounds.UNBOUNDED);
+            } else {
+                // Can't reorder CONVERT LEFT and LOAD RIGHT
+                loadExpression(rhs, TypeBounds.UNBOUNDED);
+                if (lhsLoadedType != Type.NUMBER) {
+                    method.swap();
+                    emitObjectToNumberComparisonConversion(method, tt);
+                    method.swap();
+                }
+            }
+
+            // CONVERT RIGHT
+            emitObjectToNumberComparisonConversion(method, tt);
+            return method;
+        }
+        // For primitive operands, just don't do anything special.
+        return loadBinaryOperands(cmp);
+    }
+
+    private static void emitObjectToNumberComparisonConversion(final MethodEmitter method, final TokenType tt) {
+        switch(tt) {
+        case EQ:
+        case NE:
+            if (method.peekType().isObject()) {
+                TO_NUMBER_FOR_EQ.invoke(method);
+                return;
+            }
+            break;
+        case EQ_STRICT:
+        case NE_STRICT:
+            if (method.peekType().isObject()) {
+                TO_NUMBER_FOR_STRICT_EQ.invoke(method);
+                return;
+            }
+            break;
+        default:
+            break;
+        }
+        method.convert(Type.NUMBER);
+    }
+
     private static final Type undefinedToNumber(final Type type) {
         return type == Type.UNDEFINED ? Type.NUMBER : type;
     }
@@ -621,6 +751,7 @@
 
         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);
 
@@ -724,7 +855,7 @@
          */
         final CodeGenerator codegen = this;
 
-        final Node currentDiscard = codegen.lc.getCurrentDiscard();
+        final boolean isCurrentDiscard = codegen.lc.isCurrentDiscard(expr);
         expr.accept(new NodeOperatorVisitor<LexicalContext>(new LexicalContext()) {
             @Override
             public boolean enterIdentNode(final IdentNode identNode) {
@@ -786,72 +917,84 @@
 
             @Override
             public boolean enterASSIGN(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_ADD(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_ADD(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_BIT_AND(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_BIT_AND(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_BIT_OR(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_BIT_OR(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_BIT_XOR(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_BIT_XOR(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_DIV(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_DIV(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_MOD(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_MOD(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_MUL(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_MUL(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_SAR(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_SAR(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_SHL(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_SHL(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_SHR(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_SHR(binaryNode);
                 return false;
             }
 
             @Override
             public boolean enterASSIGN_SUB(final BinaryNode binaryNode) {
+                checkAssignTarget(binaryNode.lhs());
                 loadASSIGN_SUB(binaryNode);
                 return false;
             }
@@ -1061,13 +1204,14 @@
 
             @Override
             public boolean enterDECINC(final UnaryNode unaryNode) {
+                checkAssignTarget(unaryNode.getExpression());
                 loadDECINC(unaryNode);
                 return false;
             }
 
             @Override
             public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression joinExpr) {
-                loadExpression(joinExpr.getExpression(), resultBounds);
+                loadMaybeDiscard(joinExpr, joinExpr.getExpression(), resultBounds);
                 return false;
             }
 
@@ -1084,7 +1228,7 @@
                 throw new AssertionError(otherNode.getClass().getName());
             }
         });
-        if(currentDiscard != expr) {
+        if(!isCurrentDiscard) {
             coerceStackTop(resultBounds);
         }
         return method;
@@ -1109,7 +1253,14 @@
 
     @Override
     public boolean enterBlock(final Block block) {
-        method.label(block.getEntryLabel());
+        final Label entryLabel = block.getEntryLabel();
+        if (entryLabel.isBreakTarget()) {
+            // Entry label is a break target only for an inlined finally block.
+            assert !method.isReachable();
+            method.breakLabel(entryLabel, lc.getUsedSlotCount());
+        } else {
+            method.label(entryLabel);
+        }
         if(!method.isReachable()) {
             return false;
         }
@@ -1122,7 +1273,7 @@
         return true;
     }
 
-    private boolean useOptimisticTypes() {
+    boolean useOptimisticTypes() {
         return !lc.inSplitNode() && compiler.useOptimisticTypes();
     }
 
@@ -1239,6 +1390,11 @@
         return enterJumpStatement(breakNode);
     }
 
+    @Override
+    public boolean enterJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+        return enterJumpStatement(jumpToInlinedFinally);
+    }
+
     private boolean enterJumpStatement(final JumpStatement jump) {
         if(!method.isReachable()) {
             return false;
@@ -1246,9 +1402,8 @@
         enterStatement(jump);
 
         method.beforeJoinPoint(jump);
-        final BreakableNode target = jump.getTarget(lc);
-        popScopesUntil(target);
-        final Label targetLabel = jump.getTargetLabel(target);
+        popScopesUntil(jump.getPopScopeLimit(lc));
+        final Label targetLabel = jump.getTargetLabel(lc);
         targetLabel.markAsBreakTarget();
         method._goto(targetLabel);
 
@@ -1278,12 +1433,10 @@
         final Block currentBlock = lc.getCurrentBlock();
         final CodeGeneratorLexicalContext codegenLexicalContext = lc;
 
-        function.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
-
+        function.accept(new SimpleNodeVisitor() {
             private MethodEmitter sharedScopeCall(final IdentNode identNode, final int flags) {
                 final Symbol symbol = identNode.getSymbol();
                 final boolean isFastScope = isFastScope(symbol);
-                final int scopeCallFlags = flags | (isFastScope ? CALLSITE_FAST_SCOPE : 0);
                 new OptimisticOperation(callNode, resultBounds) {
                     @Override
                     void loadStack() {
@@ -1306,7 +1459,7 @@
                         // 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);
+                                identNode.getType(), resultBounds.widest, paramTypes, flags);
                         scopeCall.generateInvoke(method);
                     }
                 }.emit();
@@ -1325,7 +1478,7 @@
                     }
                     @Override
                     void consumeStack() {
-                        dynamicCall(2 + argsCount, flags);
+                        dynamicCall(2 + argsCount, flags, ident.getName());
                     }
                 }.emit();
             }
@@ -1339,7 +1492,7 @@
                     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
@@ -1383,7 +1536,7 @@
                     @Override
                     void consumeStack() {
                         // Ordinary call
-                        dynamicCall(2 + argsCount, flags);
+                        dynamicCall(2 + argsCount, flags, "eval");
                         method._goto(eval_done);
 
                         method.label(invoke_direct_eval);
@@ -1407,7 +1560,7 @@
                 final Symbol symbol = node.getSymbol();
 
                 if (symbol.isScope()) {
-                    final int flags = getCallSiteFlags() | CALLSITE_SCOPE;
+                    final int flags = getScopeCallSiteFlags(symbol);
                     final int useCount = symbol.getUseCount();
 
                     // Threshold for generating shared scope callsite is lower for fast scope symbols because we know
@@ -1418,7 +1571,7 @@
                     } else if (useCount <= SharedScopeCall.FAST_SCOPE_CALL_THRESHOLD
                             || !isFastScope(symbol) && useCount <= SharedScopeCall.SLOW_SCOPE_CALL_THRESHOLD
                             || CodeGenerator.this.lc.inDynamicScope()
-                            || isOptimisticOrRestOf()) {
+                            || callNode.isOptimistic()) {
                         scopeCall(node, flags);
                     } else {
                         sharedScopeCall(node, flags);
@@ -1455,7 +1608,7 @@
                     }
                     @Override
                     void consumeStack() {
-                        dynamicCall(2 + argCount, flags);
+                        dynamicCall(2 + argCount, flags, node.toString(false));
                     }
                 }.emit();
 
@@ -1480,9 +1633,7 @@
 
                     @Override
                     void consumeStack() {
-                        final int flags = getCallSiteFlags();
-                        //assert callNodeType.equals(callee.getReturnType()) : callNodeType + " != " + callee.getReturnType();
-                        dynamicCall(2 + argsCount, flags);
+                        dynamicCall(2 + argsCount, getCallSiteFlags(), null);
                     }
                 }.emit();
                 return false;
@@ -1511,8 +1662,7 @@
                     }
                     @Override
                     void consumeStack() {
-                        final int flags = getCallSiteFlags();
-                        dynamicCall(2 + argsCount, flags);
+                        dynamicCall(2 + argsCount, getCallSiteFlags(), node.toString(false));
                     }
                 }.emit();
                 return false;
@@ -1532,7 +1682,7 @@
                         @Override
                         void consumeStack() {
                             final int flags = getCallSiteFlags() | CALLSITE_SCOPE;
-                            dynamicCall(2 + argsCount, flags);
+                            dynamicCall(2 + argsCount, flags, node.toString(false));
                         }
                 }.emit();
                 return false;
@@ -1558,11 +1708,7 @@
 
     @Override
     public boolean enterEmptyNode(final EmptyNode emptyNode) {
-        if(!method.isReachable()) {
-            return false;
-        }
-        enterStatement(emptyNode);
-
+        // Don't even record the line number, it's irrelevant as there's no code.
         return false;
     }
 
@@ -1760,10 +1906,10 @@
                         //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) {
+                            if (!useDualFields() ||  value == null || paramType == null || paramType.isBoolean()) {
                                 return Object.class;
                             }
-                            return paramType.isBoolean() ? Object.class : paramType.getTypeClass();
+                            return paramType.getTypeClass();
                         }
                     });
                 }
@@ -1922,8 +2068,6 @@
 
     @Override
     public boolean enterFunctionNode(final 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.
@@ -1961,9 +2105,9 @@
             method.begin();
 
             if (isRestOf()) {
-                final ContinuationInfo ci = new ContinuationInfo();
-                fnIdToContinuationInfo.put(fnId, ci);
-                method.gotoLoopStart(ci.getHandlerLabel());
+                assert continuationInfo == null;
+                continuationInfo = new ContinuationInfo();
+                method.gotoLoopStart(continuationInfo.getHandlerLabel());
             }
         }
 
@@ -1996,7 +2140,7 @@
                 markOptimistic = false;
             }
 
-            FunctionNode newFunctionNode = functionNode.setState(lc, CompilationState.BYTECODE_GENERATED);
+            FunctionNode newFunctionNode = functionNode;
             if (markOptimistic) {
                 newFunctionNode = newFunctionNode.setFlag(lc, FunctionNode.IS_DEOPTIMIZABLE);
             }
@@ -2089,73 +2233,33 @@
      *
      * @param arrayLiteralNode the array of contents
      * @param arrayType        the type of the array, e.g. ARRAY_NUMBER or ARRAY_OBJECT
-     *
-     * @return the method generator that was used
      */
-    private MethodEmitter loadArray(final ArrayLiteralNode arrayLiteralNode, final ArrayType arrayType) {
+    private void loadArray(final ArrayLiteralNode arrayLiteralNode, final ArrayType arrayType) {
         assert arrayType == Type.INT_ARRAY || arrayType == Type.LONG_ARRAY || arrayType == Type.NUMBER_ARRAY || arrayType == Type.OBJECT_ARRAY;
 
-        final Expression[]    nodes    = arrayLiteralNode.getValue();
-        final Object          presets  = arrayLiteralNode.getPresets();
-        final int[]           postsets = arrayLiteralNode.getPostsets();
-        final Class<?>        type     = arrayType.getTypeClass();
-        final List<ArrayUnit> units    = arrayLiteralNode.getUnits();
+        final Expression[]     nodes    = arrayLiteralNode.getValue();
+        final Object           presets  = arrayLiteralNode.getPresets();
+        final int[]            postsets = arrayLiteralNode.getPostsets();
+        final List<Splittable.SplitRange> ranges   = arrayLiteralNode.getSplitRanges();
 
         loadConstant(presets);
 
         final Type elementType = arrayType.getElementType();
 
-        if (units != null) {
-            final MethodEmitter savedMethod     = method;
-            final FunctionNode  currentFunction = lc.getCurrentFunction();
+        if (ranges != null) {
 
-            for (final ArrayUnit arrayUnit : units) {
-                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);
-
-                pushMethodEmitter(unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature));
-
-                method.setFunctionNode(currentFunction);
-                method.begin();
-
-                defineCommonSplitMethodParameters();
-                defineSplitMethodParameter(CompilerConstants.SPLIT_ARRAY_ARG.slot(), arrayType);
-
-                // NOTE: when this is no longer needed, SplitIntoFunctions will no longer have to add IS_SPLIT
-                // to synthetic functions, and FunctionNode.needsCallee() will no longer need to test for isSplit().
-                final int arraySlot = fixScopeSlot(currentFunction, 3);
-
-                lc.enterSplitNode();
-
-                for (int i = arrayUnit.getLo(); i < arrayUnit.getHi(); i++) {
-                    method.load(arrayType, arraySlot);
-                    storeElement(nodes, elementType, postsets[i]);
+            loadSplitLiteral(new SplitLiteralCreator() {
+                @Override
+                public void populateRange(final MethodEmitter method, final Type type, final int slot, final int start, final int end) {
+                    for (int i = start; i < end; i++) {
+                        method.load(type, slot);
+                        storeElement(nodes, elementType, postsets[i]);
+                    }
+                    method.load(type, slot);
                 }
+            }, ranges, arrayType);
 
-                method.load(arrayType, arraySlot);
-                method._return();
-                lc.exitSplitNode();
-                method.end();
-                lc.releaseSlots();
-                popMethodEmitter();
-
-                assert method == savedMethod;
-                method.loadCompilerConstant(CALLEE);
-                method.swap();
-                method.loadCompilerConstant(THIS);
-                method.swap();
-                method.loadCompilerConstant(SCOPE);
-                method.swap();
-                method.invokestatic(className, name, signature);
-
-                unit = lc.popCompileUnit(unit);
-            }
-
-            return method;
+            return;
         }
 
         if(postsets.length > 0) {
@@ -2167,7 +2271,6 @@
             }
             method.load(arrayType, arraySlot);
         }
-        return method;
     }
 
     private void storeElement(final Expression[] nodes, final Type elementType, final int index) {
@@ -2242,7 +2345,6 @@
         } else {
             methodEmitter.loadConstants().load(index).arrayload();
             if (object instanceof ArrayData) {
-                // avoid cast to non-public ArrayData subclass
                 methodEmitter.checkcast(ArrayData.class);
                 methodEmitter.invoke(virtualCallNoLookup(ArrayData.class, "copy", ArrayData.class));
             } else if (cls != Object.class) {
@@ -2251,6 +2353,10 @@
         }
     }
 
+    private void loadConstantsAndIndex(final Object object, final MethodEmitter methodEmitter) {
+        methodEmitter.loadConstants().load(compiler.getConstantData().add(object));
+    }
+
     // literal values
     private void loadLiteral(final LiteralNode<?> node, final TypeBounds resultBounds) {
         final Object value = node.getValue();
@@ -2354,7 +2460,7 @@
 
             @Override
             public Boolean get() {
-                value.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+                value.accept(new SimpleNodeVisitor() {
                     @Override
                     public boolean enterFunctionNode(final FunctionNode functionNode) {
                         return false;
@@ -2389,6 +2495,7 @@
         final List<MapTuple<Expression>> tuples = new ArrayList<>();
         final List<PropertyNode> gettersSetters = new ArrayList<>();
         final int ccp = getCurrentContinuationEntryPoint();
+        final List<Splittable.SplitRange> ranges = objectNode.getSplitRanges();
 
         Expression protoNode = null;
         boolean restOfProperty = false;
@@ -2416,7 +2523,7 @@
 
             //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();
+            final Class<?> valueType = (!useDualFields() || 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() {
@@ -2435,7 +2542,13 @@
                     loadExpressionAsType(node, type);
                 }};
         }
-        oc.makeObject(method);
+
+        if (ranges != null) {
+            oc.createObject(method);
+            loadSplitLiteral(oc, ranges, Type.typeFor(oc.getAllocatorClass()));
+        } else {
+            oc.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
@@ -2488,8 +2601,6 @@
         }
         enterStatement(returnNode);
 
-        method.registerReturn();
-
         final Type returnType = lc.getCurrentFunction().getReturnType();
 
         final Expression expression = returnNode.getExpression();
@@ -2687,7 +2798,7 @@
             boolean contains;
             @Override
             public Boolean get() {
-                rootExpr.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+                rootExpr.accept(new SimpleNodeVisitor() {
                     @Override
                     public boolean enterFunctionNode(final FunctionNode functionNode) {
                         return false;
@@ -2722,25 +2833,18 @@
             newRuntimeNode = runtimeNode;
         }
 
-        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();
+        for (final Expression arg : args) {
+            loadExpression(arg, TypeBounds.OBJECT);
+        }
+
+        method.invokestatic(
+                CompilerConstants.className(ScriptRuntime.class),
+                newRuntimeNode.getRequest().toString(),
+                new FunctionSignature(
+                    false,
+                    false,
+                    newRuntimeNode.getType(),
+                    args.size()).toString());
 
         method.convert(newRuntimeNode.getType());
     }
@@ -2760,6 +2864,54 @@
         method.onLocalStore(type, slot);
     }
 
+    private void loadSplitLiteral(final SplitLiteralCreator creator, final List<Splittable.SplitRange> ranges, final Type literalType) {
+        assert ranges != null;
+
+        // final Type literalType = Type.typeFor(literalClass);
+        final MethodEmitter savedMethod     = method;
+        final FunctionNode  currentFunction = lc.getCurrentFunction();
+
+        for (final Splittable.SplitRange splitRange : ranges) {
+            unit = lc.pushCompileUnit(splitRange.getCompileUnit());
+
+            assert unit != null;
+            final String className = unit.getUnitClassName();
+            final String name      = currentFunction.uniqueName(SPLIT_PREFIX.symbolName());
+            final Class<?> clazz   = literalType.getTypeClass();
+            final String signature = methodDescriptor(clazz, ScriptFunction.class, Object.class, ScriptObject.class, clazz);
+
+            pushMethodEmitter(unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature));
+
+            method.setFunctionNode(currentFunction);
+            method.begin();
+
+            defineCommonSplitMethodParameters();
+            defineSplitMethodParameter(CompilerConstants.SPLIT_ARRAY_ARG.slot(), literalType);
+
+            // NOTE: when this is no longer needed, SplitIntoFunctions will no longer have to add IS_SPLIT
+            // to synthetic functions, and FunctionNode.needsCallee() will no longer need to test for isSplit().
+            final int literalSlot = fixScopeSlot(currentFunction, 3);
+
+            lc.enterSplitNode();
+
+            creator.populateRange(method, literalType, literalSlot, splitRange.getLow(), splitRange.getHigh());
+
+            method._return();
+            lc.exitSplitNode();
+            method.end();
+            lc.releaseSlots();
+            popMethodEmitter();
+
+            assert method == savedMethod;
+            method.loadCompilerConstant(CALLEE).swap();
+            method.loadCompilerConstant(THIS).swap();
+            method.loadCompilerConstant(SCOPE).swap();
+            method.invokestatic(className, name, signature);
+
+            unit = lc.popCompileUnit(unit);
+        }
+    }
+
     private int fixScopeSlot(final FunctionNode functionNode, final int extraSlot) {
         // TODO hack to move the scope to the expected slot (needed because split methods reuse the same slots as the root method)
         final int actualScopeSlot = functionNode.compilerConstant(SCOPE).getSlot(SCOPE_TYPE);
@@ -3049,6 +3201,14 @@
         if (method.isReachable()) {
             method._goto(skip);
         }
+
+        for (final Block inlinedFinally : tryNode.getInlinedFinallies()) {
+            TryNode.getLabelledInlinedFinallyBlock(inlinedFinally).accept(this);
+            // All inlined finallies end with a jump or a return
+            assert !method.isReachable();
+        }
+
+
         method._catch(recovery);
         method.store(vmException, EXCEPTION_TYPE);
 
@@ -3099,6 +3259,7 @@
             if (isConditionalCatch) {
                 loadExpressionAsBoolean(exceptionCondition);
                 nextCatch = new Label("next_catch");
+                nextCatch.markAsBreakTarget();
                 method.ifeq(nextCatch);
             } else {
                 nextCatch = null;
@@ -3107,15 +3268,14 @@
             catchBody.accept(this);
             leaveBlock(catchBlock);
             lc.pop(catchBlock);
-            if(method.isReachable()) {
-                method._goto(afterCatch);
-            }
             if(nextCatch != null) {
-                method.label(nextCatch);
+                if(method.isReachable()) {
+                    method._goto(afterCatch);
+                }
+                method.breakLabel(nextCatch, lc.getUsedSlotCount());
             }
         }
 
-        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()) {
@@ -3124,6 +3284,8 @@
         method.label(skip);
 
         // Finally body is always inlined elsewhere so it doesn't need to be emitted
+        assert tryNode.getFinallyBody() == null;
+
         return false;
     }
 
@@ -3143,7 +3305,7 @@
                 // block scoped variables need a DECLARE flag to signal end of temporal dead zone (TDZ)
                 method.loadCompilerConstant(SCOPE);
                 method.loadUndefined(Type.OBJECT);
-                final int flags = CALLSITE_SCOPE | getCallSiteFlags() | (varNode.isBlockScoped() ? CALLSITE_DECLARE : 0);
+                final int flags = getScopeCallSiteFlags(identSymbol) | (varNode.isBlockScoped() ? CALLSITE_DECLARE : 0);
                 assert isFastScope(identSymbol);
                 storeFastScopeVar(identSymbol, flags);
             }
@@ -3160,7 +3322,7 @@
         if (needsScope) {
             loadExpressionUnbounded(init);
             // block scoped variables need a DECLARE flag to signal end of temporal dead zone (TDZ)
-            final int flags = CALLSITE_SCOPE | getCallSiteFlags() | (varNode.isBlockScoped() ? CALLSITE_DECLARE : 0);
+            final int flags = getScopeCallSiteFlags(identSymbol) | (varNode.isBlockScoped() ? CALLSITE_DECLARE : 0);
             if (isFastScope(identSymbol)) {
                 storeFastScopeVar(identSymbol, flags);
             } else {
@@ -3506,7 +3668,7 @@
         // 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;
+            assert !lc.isCurrentDiscard(expr);
             // Don't bother evaluating expressions without side effects. Typical usage is "void 0" for reliably generating
             // undefined.
             return;
@@ -3514,11 +3676,37 @@
 
         lc.pushDiscard(expr);
         loadExpression(expr, TypeBounds.UNBOUNDED);
-        if (lc.getCurrentDiscard() == expr) {
+        if (lc.popDiscardIfCurrent(expr)) {
             assert !expr.isAssignment();
             // NOTE: if we had a way to load with type void, we could avoid popping
             method.pop();
-            lc.popDiscard();
+        }
+    }
+
+    /**
+     * Loads the expression with the specified type bounds, but if the parent expression is the current discard,
+     * then instead loads and discards the expression.
+     * @param parent the parent expression that's tested for being the current discard
+     * @param expr the expression that's either normally loaded or discard-loaded
+     * @param resultBounds result bounds for when loading the expression normally
+     */
+    private void loadMaybeDiscard(final Expression parent, final Expression expr, final TypeBounds resultBounds) {
+        loadMaybeDiscard(lc.popDiscardIfCurrent(parent), expr, resultBounds);
+    }
+
+    /**
+     * Loads the expression with the specified type bounds, or loads and discards the expression, depending on the
+     * value of the discard flag. Useful as a helper for expressions with control flow where you often can't combine
+     * testing for being the current discard and loading the subexpressions.
+     * @param discard if true, the expression is loaded and discarded
+     * @param expr the expression that's either normally loaded or discard-loaded
+     * @param resultBounds result bounds for when loading the expression normally
+     */
+    private void loadMaybeDiscard(final boolean discard, final Expression expr, final TypeBounds resultBounds) {
+        if (discard) {
+            loadAndDiscard(expr);
+        } else {
+            loadExpression(expr, resultBounds);
         }
     }
 
@@ -3526,10 +3714,11 @@
         final CallNode callNode = (CallNode)unaryNode.getExpression();
         final List<Expression> args   = callNode.getArgs();
 
+        final Expression func = callNode.getFunction();
         // Load function reference.
-        loadExpressionAsObject(callNode.getFunction()); // must detect type error
+        loadExpressionAsObject(func); // must detect type error
 
-        method.dynamicNew(1 + loadArgs(args), getCallSiteFlags());
+        method.dynamicNew(1 + loadArgs(args), getCallSiteFlags(), func.toString(false));
     }
 
     private void loadNOT(final UnaryNode unaryNode) {
@@ -3575,9 +3764,7 @@
 
     public void loadVOID(final UnaryNode unaryNode, final TypeBounds resultBounds) {
         loadAndDiscard(unaryNode.getExpression());
-        if(lc.getCurrentDiscard() == unaryNode) {
-            lc.popDiscard();
-        } else {
+        if (!lc.popDiscardIfCurrent(unaryNode)) {
             method.loadUndefined(resultBounds.widest);
         }
     }
@@ -3610,16 +3797,22 @@
     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 boolean isCurrentDiscard = lc.popDiscardIfCurrent(binaryNode);
+
         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);
+            if (isCurrentDiscard) {
+                method.label(onTrue);
+            } else {
+                method.load(false);
+                method._goto(skip);
+                method.label(onTrue);
+                method.load(true);
+                method.label(skip);
+            }
             return;
         }
 
@@ -3628,7 +3821,11 @@
         final boolean lhsConvert = LocalVariableConversion.hasLiveConversion(lhs);
         final Label evalRhs = lhsConvert ? new Label("eval_rhs") : null;
 
-        loadExpression(lhs, outBounds).dup().convert(Type.BOOLEAN);
+        loadExpression(lhs, outBounds);
+        if (!isCurrentDiscard) {
+            method.dup();
+        }
+        method.convert(Type.BOOLEAN);
         if (isAnd) {
             if(lhsConvert) {
                 method.ifne(evalRhs);
@@ -3647,9 +3844,11 @@
             method.label(evalRhs);
         }
 
-        method.pop();
+        if (!isCurrentDiscard) {
+            method.pop();
+        }
         final JoinPredecessorExpression rhs = (JoinPredecessorExpression)binaryNode.rhs();
-        loadExpression(rhs, outBounds);
+        loadMaybeDiscard(isCurrentDiscard, rhs, outBounds);
         method.beforeJoinPoint(rhs);
         method.label(skip);
     }
@@ -3671,9 +3870,8 @@
         // Detect dead assignments
         if(lhs instanceof IdentNode) {
             final Symbol symbol = ((IdentNode)lhs).getSymbol();
-            if(!symbol.isScope() && !symbol.hasSlotFor(rhsType) && lc.getCurrentDiscard() == binaryNode) {
+            if(!symbol.isScope() && !symbol.hasSlotFor(rhsType) && lc.popDiscardIfCurrent(binaryNode)) {
                 loadAndDiscard(rhs);
-                lc.popDiscard();
                 method.markDeadLocalVariable(symbol);
                 return;
             }
@@ -3927,11 +4125,11 @@
 
     private void loadCOMMARIGHT(final BinaryNode binaryNode, final TypeBounds resultBounds) {
         loadAndDiscard(binaryNode.lhs());
-        loadExpression(binaryNode.rhs(), resultBounds);
+        loadMaybeDiscard(binaryNode, binaryNode.rhs(), resultBounds);
     }
 
     private void loadCOMMALEFT(final BinaryNode binaryNode, final TypeBounds resultBounds) {
-        loadExpression(binaryNode.lhs(), resultBounds);
+        loadMaybeDiscard(binaryNode, binaryNode.lhs(), resultBounds);
         loadAndDiscard(binaryNode.rhs());
     }
 
@@ -3945,8 +4143,7 @@
     }
 
     private void loadCmp(final BinaryNode binaryNode, final Condition cond) {
-        assert comparisonOperandsArePrimitive(binaryNode) : binaryNode;
-        loadBinaryOperands(binaryNode);
+        loadComparisonOperands(binaryNode);
 
         final Label trueLabel  = new Label("trueLabel");
         final Label afterLabel = new Label("skip");
@@ -3960,11 +4157,6 @@
         method.label(afterLabel);
     }
 
-    private static boolean comparisonOperandsArePrimitive(final BinaryNode binaryNode) {
-        final Type widest = Type.widest(binaryNode.lhs().getType(), binaryNode.rhs().getType());
-        return widest.isNumeric() || widest.isBoolean();
-    }
-
     private void loadMOD(final BinaryNode binaryNode, final TypeBounds resultBounds) {
         new BinaryArith() {
             @Override
@@ -4037,13 +4229,14 @@
 
         emitBranch(test, falseLabel, false);
 
-        loadExpression(trueExpr.getExpression(), outBounds);
-        assert Type.generic(method.peekType()) == outBounds.narrowest;
+        final boolean isCurrentDiscard = lc.popDiscardIfCurrent(ternaryNode);
+        loadMaybeDiscard(isCurrentDiscard, trueExpr.getExpression(), outBounds);
+        assert isCurrentDiscard || Type.generic(method.peekType()) == outBounds.narrowest;
         method.beforeJoinPoint(trueExpr);
         method._goto(exitLabel);
         method.label(falseLabel);
-        loadExpression(falseExpr.getExpression(), outBounds);
-        assert Type.generic(method.peekType()) == outBounds.narrowest;
+        loadMaybeDiscard(isCurrentDiscard, falseExpr.getExpression(), outBounds);
+        assert isCurrentDiscard || Type.generic(method.peekType()) == outBounds.narrowest;
         method.beforeJoinPoint(falseExpr);
         method.label(exitLabel);
     }
@@ -4148,12 +4341,12 @@
         }
 
         private void prologue() {
-            /**
+            /*
              * 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
              */
 
-            target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+            target.accept(new SimpleNodeVisitor() {
                 @Override
                 public boolean enterIdentNode(final IdentNode node) {
                     if (node.getSymbol().isScope()) {
@@ -4229,9 +4422,8 @@
 
         // store the result that "lives on" after the op, e.g. "i" in i++ postfix.
         protected void storeNonDiscard() {
-            if (lc.getCurrentDiscard() == assignNode) {
+            if (lc.popDiscardIfCurrent(assignNode)) {
                 assert assignNode.isAssignment();
-                lc.popDiscard();
                 return;
             }
 
@@ -4253,7 +4445,7 @@
              * need to do a conversion on non-equivalent types exists, but is
              * very rare. See for example test/script/basic/access-specializer.js
              */
-            target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+            target.accept(new SimpleNodeVisitor() {
                 @Override
                 protected boolean enterDefault(final Node node) {
                     throw new AssertionError("Unexpected node " + node + " in store epilogue");
@@ -4264,7 +4456,7 @@
                     final Symbol symbol = node.getSymbol();
                     assert symbol != null;
                     if (symbol.isScope()) {
-                        final int flags = CALLSITE_SCOPE | getCallSiteFlags();
+                        final int flags = getScopeCallSiteFlags(symbol);
                         if (isFastScope(symbol)) {
                             storeFastScopeVar(symbol, flags);
                         } else {
@@ -4322,21 +4514,19 @@
         final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(functionNode.getId());
 
         if (functionNode.isProgram() && !compiler.isOnDemandCompilation()) {
-            final CompileUnit fnUnit = functionNode.getCompileUnit();
-            final MethodEmitter createFunction = fnUnit.getClassEmitter().method(
+            final MethodEmitter createFunction = functionNode.getCompileUnit().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);
+            loadConstantsAndIndex(data, createFunction);
             createFunction.load(SCOPE_TYPE, 0);
-            createFunction.invoke(constructorNoLookup(SCRIPTFUNCTION_IMPL_NAME, RecompilableScriptFunctionData.class, ScriptObject.class));
+            createFunction.invoke(CREATE_FUNCTION_OBJECT);
             createFunction._return();
             createFunction.end();
         }
 
         if (addInitializer && !compiler.isOnDemandCompilation()) {
-            compiler.addFunctionInitializer(data, functionNode);
+            functionNode.getCompileUnit().addFunctionInitializer(data, functionNode);
         }
 
         // We don't emit a ScriptFunction on stack for the outermost compiled function (as there's no code being
@@ -4345,15 +4535,14 @@
             return;
         }
 
-        method._new(SCRIPTFUNCTION_IMPL_NAME, SCRIPTFUNCTION_IMPL_TYPE).dup();
-        loadConstant(data);
+        loadConstantsAndIndex(data, method);
 
         if (functionNode.needsParentScope()) {
             method.loadCompilerConstant(SCOPE);
+            method.invoke(CREATE_FUNCTION_OBJECT);
         } else {
-            method.loadNull();
+            method.invoke(CREATE_FUNCTION_OBJECT_NO_SCOPE);
         }
-        method.invoke(constructorNoLookup(SCRIPTFUNCTION_IMPL_NAME, RecompilableScriptFunctionData.class, ScriptObject.class));
     }
 
     // calls on Global class.
@@ -4620,7 +4809,7 @@
          * 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
+         * @param isMethod whether we're preferably retrieving a function
          * @return the current method emitter
          */
         MethodEmitter dynamicGet(final String name, final int flags, final boolean isMethod, final boolean isIndex) {
@@ -4637,11 +4826,11 @@
             return method.dynamicGetIndex(resultBounds.within(expression.getType()), nonOptimisticFlags(flags), isMethod);
         }
 
-        MethodEmitter dynamicCall(final int argCount, final int flags) {
+        MethodEmitter dynamicCall(final int argCount, final int flags, final String msg) {
             if (isOptimistic) {
-                return method.dynamicCall(getOptimisticCoercedType(), argCount, getOptimisticFlags(flags));
+                return method.dynamicCall(getOptimisticCoercedType(), argCount, getOptimisticFlags(flags), msg);
             }
-            return method.dynamicCall(resultBounds.within(expression.getType()), argCount, nonOptimisticFlags(flags));
+            return method.dynamicCall(resultBounds.within(expression.getType()), argCount, nonOptimisticFlags(flags), msg);
         }
 
         int getOptimisticFlags(final int flags) {
@@ -5052,7 +5241,7 @@
         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
+        // Object literal stack depth for object literal - not necessarily top if property is a tree
         private int objectLiteralStackDepth = -1;
         // The line number at the continuation point
         private int lineNumber;
@@ -5129,7 +5318,7 @@
     }
 
     private ContinuationInfo getContinuationInfo() {
-        return fnIdToContinuationInfo.get(lc.getCurrentFunction().getId());
+        return continuationInfo;
     }
 
     private void generateContinuationHandler() {
@@ -5217,7 +5406,7 @@
                 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
+                // change map of s0 so that the property we are initializing when we failed
                 // is now ci.returnValueType
                 if (i == objectLiteralStackDepth) {
                     method.dup();
@@ -5285,4 +5474,21 @@
             method.uncheckedGoto(targetCatchLabel);
         }
     }
+
+    /**
+     * Interface implemented by object creators that support splitting over multiple methods.
+     */
+    interface SplitLiteralCreator {
+        /**
+         * Generate code to populate a range of the literal object. A reference to the object
+         * should be left on the stack when the method terminates.
+         *
+         * @param method the method emitter
+         * @param type the type of the literal object
+         * @param slot the local slot containing the literal object
+         * @param start the start index (inclusive)
+         * @param end the end index (exclusive)
+         */
+        void populateRange(MethodEmitter method, Type type, int slot, int start, int end);
+    }
 }
diff --git a/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java b/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java
index 87a0802..6312714 100644
--- a/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java
+++ b/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java
@@ -34,6 +34,7 @@
 import jdk.nashorn.internal.IntDeque;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.Block;
+import jdk.nashorn.internal.ir.Expression;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LexicalContextNode;
@@ -59,9 +60,11 @@
     /** Method emitter stack - every time we start a sub method (e.g. a split) we push one */
     private final Deque<MethodEmitter> methodEmitters = new ArrayDeque<>();
 
-    /** The discard stack - whenever we enter a discard node we keep track of its return value status -
-     *  i.e. should we keep it or throw it away */
-    private final Deque<Node> discard = new ArrayDeque<>();
+    /** The discard stack - whenever we evaluate an expression that will be discarded, we push it on this stack. Various
+     * implementations of expression code emitter can choose to emit code that'll discard the expression themselves, or
+     * ignore it in which case CodeGenerator.loadAndDiscard() will explicitly emit a pop instruction. */
+    private final Deque<Expression> discard = new ArrayDeque<>();
+
 
     private final Deque<Map<String, Collection<Label>>> unwarrantedOptimismHandlers = new ArrayDeque<>();
     private final Deque<StringBuilder> slotTypesDescriptors = new ArrayDeque<>();
@@ -74,7 +77,7 @@
     /** size of next free slot vector */
     private int nextFreeSlotsSize;
 
-    private boolean isWithBoundary(final LexicalContextNode node) {
+    private boolean isWithBoundary(final Object node) {
         return node instanceof Block && !isEmpty() && peek() instanceof WithNode;
     }
 
@@ -102,7 +105,7 @@
     }
 
     @Override
-    public <T extends LexicalContextNode> T pop(final T node) {
+    public <T extends Node> T pop(final T node) {
         final T popped = super.pop(node);
         if (isWithBoundary(node)) {
             dynamicScopeCount--;
@@ -270,16 +273,20 @@
         }
     }
 
-    void pushDiscard(final Node node) {
-        discard.push(node);
+    void pushDiscard(final Expression expr) {
+        discard.push(expr);
     }
 
-    Node popDiscard() {
-        return discard.pop();
+    boolean popDiscardIfCurrent(final Expression expr) {
+        if (isCurrentDiscard(expr)) {
+            discard.pop();
+            return true;
+        }
+        return false;
     }
 
-    Node getCurrentDiscard() {
-        return discard.peek();
+    boolean isCurrentDiscard(final Expression expr) {
+        return discard.peek() == expr;
     }
 
     int quickSlot(final Type type) {
diff --git a/src/jdk/nashorn/internal/codegen/CompilationPhase.java b/src/jdk/nashorn/internal/codegen/CompilationPhase.java
index 2a1d266..e0a6945 100644
--- a/src/jdk/nashorn/internal/codegen/CompilationPhase.java
+++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java
@@ -25,39 +25,25 @@
 
 package jdk.nashorn.internal.codegen;
 
-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.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.PrintWriter;
-import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
-import jdk.nashorn.internal.AssertsEnabled;
 import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
+import jdk.nashorn.internal.ir.Block;
 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.Node;
+import jdk.nashorn.internal.ir.Symbol;
 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.ir.visitor.SimpleNodeVisitor;
 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.logging.DebugLogger;
@@ -66,15 +52,9 @@
  * A compilation phase is a step in the processes of turning a JavaScript
  * FunctionNode into bytecode. It has an optional return value.
  */
-enum CompilationPhase {
-    /**
-     * Constant folding pass Simple constant folding that will make elementary
-     * constructs go away
-     */
-    CONSTANT_FOLDING_PHASE(
-            EnumSet.of(
-                INITIALIZED,
-                PARSED)) {
+abstract class CompilationPhase {
+
+    private static final class ConstantFoldingPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             return transformFunction(fn, new FoldConstants(compiler));
@@ -84,20 +64,15 @@
         public String toString() {
             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.
+     * Constant folding pass Simple constant folding that will make elementary
+     * constructs go away
      */
-    LOWERING_PHASE(
-            EnumSet.of(
-                INITIALIZED,
-                PARSED,
-                CONSTANT_FOLDED)) {
+    static final CompilationPhase CONSTANT_FOLDING_PHASE = new ConstantFoldingPhase();
+
+    private static final class LoweringPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             return transformFunction(fn, new Lower(compiler));
@@ -107,42 +82,35 @@
         public String toString() {
             return "'Control Flow Lowering'";
         }
-    },
+    }
 
     /**
-     * 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
+     * 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.
      */
-    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
+    static final CompilationPhase LOWERING_PHASE = new LoweringPhase();
+
+    private static final class ApplySpecializationPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
-            return setStates(transformFunction(fn, new ApplySpecialization(compiler)), BUILTINS_TRANSFORMED);
+            return transformFunction(fn, new ApplySpecialization(compiler));
         }
 
         @Override
         public String toString() {
             return "'Builtin Replacement'";
         }
-    },
+    };
 
     /**
-     * Splitter Split the AST into several compile units based on a heuristic size calculation.
-     * Split IR can lead to scope information being changed.
+     * Phase used to transform Function.prototype.apply.
      */
-    SPLITTING_PHASE(
-            EnumSet.of(
-                    INITIALIZED,
-                    PARSED,
-                    CONSTANT_FOLDED,
-                    LOWERED,
-                    BUILTINS_TRANSFORMED)) {
+    static final CompilationPhase APPLY_SPECIALIZATION_PHASE = new ApplySpecializationPhase();
+
+    private static final class SplittingPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             final CompileUnit  outermostCompileUnit = compiler.addCompileUnit(0L);
@@ -150,7 +118,7 @@
             FunctionNode newFunctionNode;
 
             //ensure elementTypes, postsets and presets exist for splitter and arraynodes
-            newFunctionNode = transformFunction(fn, new NodeVisitor<LexicalContext>(new LexicalContext()) {
+            newFunctionNode = transformFunction(fn, new SimpleNodeVisitor() {
                 @Override
                 public LiteralNode<?> leaveLiteralNode(final LiteralNode<?> literalNode) {
                     return literalNode.initialize(lc);
@@ -169,16 +137,15 @@
         public String toString() {
             return "'Code Splitting'";
         }
-    },
+    };
 
-    PROGRAM_POINT_PHASE(
-            EnumSet.of(
-                    INITIALIZED,
-                    PARSED,
-                    CONSTANT_FOLDED,
-                    LOWERED,
-                    BUILTINS_TRANSFORMED,
-                    SPLIT)) {
+    /**
+     * Splitter Split the AST into several compile units based on a heuristic size calculation.
+     * Split IR can lead to scope information being changed.
+     */
+    static final CompilationPhase SPLITTING_PHASE = new SplittingPhase();
+
+    private static final class ProgramPointPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             return transformFunction(fn, new ProgramPoints());
@@ -188,43 +155,34 @@
         public String toString() {
             return "'Program Point Calculation'";
         }
-    },
+    };
 
-    SERIALIZE_SPLIT_PHASE(
-            EnumSet.of(
-                    INITIALIZED,
-                    PARSED,
-                    CONSTANT_FOLDED,
-                    LOWERED,
-                    BUILTINS_TRANSFORMED,
-                    SPLIT)) {
+    static final CompilationPhase PROGRAM_POINT_PHASE = new ProgramPointPhase();
+
+    private static final class CacheAstPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
-            return transformFunction(fn, new NodeVisitor<LexicalContext>(new LexicalContext()) {
-                @Override
-                public boolean enterFunctionNode(final FunctionNode functionNode) {
-                    if (functionNode.isSplit()) {
-                        compiler.serializeAst(functionNode);
-                    }
-                    return true;
-                }
-            });
+            if (!compiler.isOnDemandCompilation()) {
+                // Only do this on initial preprocessing of the source code. For on-demand compilations from
+                // source, FindScopeDepths#leaveFunctionNode() calls data.setCachedAst() for the sole function
+                // being compiled.
+                transformFunction(fn, new CacheAst(compiler));
+            }
+            // NOTE: we're returning the original fn as we have destructively modified the cached functions by
+            // removing their bodies. This step is associating FunctionNode objects with
+            // RecompilableScriptFunctionData; it's not really modifying the AST.
+            return fn;
         }
 
         @Override
         public String toString() {
-            return "'Serialize Split Functions'";
+            return "'Cache ASTs'";
         }
-    },
+    };
 
-    SYMBOL_ASSIGNMENT_PHASE(
-            EnumSet.of(
-                    INITIALIZED,
-                    PARSED,
-                    CONSTANT_FOLDED,
-                    LOWERED,
-                    BUILTINS_TRANSFORMED,
-                    SPLIT)) {
+    static final CompilationPhase CACHE_AST_PHASE = new CacheAstPhase();
+
+    private static final class SymbolAssignmentPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             return transformFunction(fn, new AssignSymbols(compiler));
@@ -234,17 +192,11 @@
         public String toString() {
             return "'Symbol Assignment'";
         }
-    },
+    };
 
-    SCOPE_DEPTH_COMPUTATION_PHASE(
-            EnumSet.of(
-                    INITIALIZED,
-                    PARSED,
-                    CONSTANT_FOLDED,
-                    LOWERED,
-                    BUILTINS_TRANSFORMED,
-                    SPLIT,
-                    SYMBOLS_ASSIGNED)) {
+    static final CompilationPhase SYMBOL_ASSIGNMENT_PHASE = new SymbolAssignmentPhase();
+
+    private static final class ScopeDepthComputationPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             return transformFunction(fn, new FindScopeDepths(compiler));
@@ -254,43 +206,66 @@
         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)) {
+    static final CompilationPhase SCOPE_DEPTH_COMPUTATION_PHASE = new ScopeDepthComputationPhase();
+
+    private static final class DeclareLocalSymbolsPhase extends CompilationPhase {
+        @Override
+        FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+            // 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()) {
+                fn.getBody().accept(new SimpleNodeVisitor() {
+                    @Override
+                    public boolean enterFunctionNode(final FunctionNode functionNode) {
+                        // OTOH, we must not declare symbols from nested functions to be locals. As we're doing on-demand
+                        // compilation, and we're skipping parsing the function bodies for nested functions, this
+                        // basically only means their parameters. It'd be enough to mistakenly declare to be a local a
+                        // symbol in the outer function named the same as one of the parameters, though.
+                        return false;
+                    };
+                    @Override
+                    public boolean enterBlock(final Block block) {
+                        for (final Symbol symbol: block.getSymbols()) {
+                            if (!symbol.isScope()) {
+                                compiler.declareLocalSymbol(symbol.getName());
+                            }
+                        }
+                        return true;
+                    };
+                });
+            }
+            return fn;
+        }
+
+        @Override
+        public String toString() {
+            return "'Local Symbols Declaration'";
+        }
+    };
+
+    static final CompilationPhase DECLARE_LOCAL_SYMBOLS_PHASE = new DeclareLocalSymbolsPhase();
+
+    private static final class OptimisticTypeAssignmentPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             if (compiler.useOptimisticTypes()) {
                 return transformFunction(fn, new OptimisticTypesCalculator(compiler));
             }
-            return setStates(fn, OPTIMISTIC_TYPES_ASSIGNED);
+            return fn;
         }
 
         @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)) {
+    static final CompilationPhase OPTIMISTIC_TYPE_ASSIGNMENT_PHASE = new OptimisticTypeAssignmentPhase();
+
+    private static final class LocalVariableTypeCalculationPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             final FunctionNode newFunctionNode = transformFunction(fn, new LocalVariableTypesCalculator(compiler));
@@ -315,25 +290,11 @@
         public String toString() {
             return "'Local Variable Type Calculation'";
         }
-    },
+    };
 
+    static final CompilationPhase LOCAL_VARIABLE_TYPE_CALCULATION_PHASE = new LocalVariableTypeCalculationPhase();
 
-    /**
-     * 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)) {
+    private static final class ReuseCompileUnitsPhase extends CompilationPhase {
         @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";
@@ -364,7 +325,7 @@
             //partial code generation
             final FunctionNode newFunctionNode = transformFunction(fn, new ReplaceCompileUnits() {
                 @Override
-                CompileUnit getReplacement(CompileUnit original) {
+                CompileUnit getReplacement(final CompileUnit original) {
                     return map.get(original);
                 }
 
@@ -381,16 +342,15 @@
         public String toString() {
             return "'Reuse Compile Units'";
         }
-    },
+    }
 
-    REINITIALIZE_SERIALIZED(
-            EnumSet.of(
-                    INITIALIZED,
-                    PARSED,
-                    CONSTANT_FOLDED,
-                    LOWERED,
-                    BUILTINS_TRANSFORMED,
-                    SPLIT)) {
+    /**
+     * Reuse compile units, if they are already present. We are using the same compiler
+     * to recompile stuff
+     */
+    static final CompilationPhase REUSE_COMPILE_UNITS_PHASE = new ReuseCompileUnitsPhase();
+
+    private static final class ReinitializeCachedPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             final Set<CompileUnit> unitSet = CompileUnit.createCompileUnitSet();
@@ -431,28 +391,13 @@
 
         @Override
         public String toString() {
-            return "'Deserialize'";
+            return "'Reinitialize cached'";
         }
-    },
+    }
 
-    /**
-     * Bytecode generation:
-     *
-     * Generate the byte code class(es) resulting from the compiled FunctionNode
-     */
-    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)) {
+    static final CompilationPhase REINITIALIZE_CACHED = new ReinitializeCachedPhase();
 
+    private static final class BytecodeGenerationPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             final ScriptEnvironment senv = compiler.getScriptEnvironment();
@@ -470,7 +415,7 @@
             try {
                 // 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 = transformFunction(newFunctionNode, codegen).setState(null, BYTECODE_GENERATED);
+                newFunctionNode = transformFunction(newFunctionNode, codegen);
                 codegen.generateScopeCalls();
             } catch (final VerifyError e) {
                 if (senv._verify_code || senv._print_code) {
@@ -518,22 +463,16 @@
         public String toString() {
             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)) {
+    /**
+     * Bytecode generation:
+     *
+     * Generate the byte code class(es) resulting from the compiled FunctionNode
+     */
+    static final CompilationPhase BYTECODE_GENERATION_PHASE = new BytecodeGenerationPhase();
 
+    private static final class InstallPhase extends CompilationPhase {
         @Override
         FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
             final DebugLogger log = compiler.getLogger();
@@ -544,8 +483,8 @@
             Class<?> rootClass = null;
             long length = 0L;
 
-            final CodeInstaller<ScriptEnvironment> codeInstaller = compiler.getCodeInstaller();
-            final Map<String, byte[]>              bytecode      = compiler.getBytecode();
+            final CodeInstaller       codeInstaller = compiler.getCodeInstaller();
+            final Map<String, byte[]> bytecode      = compiler.getBytecode();
 
             for (final Entry<String, byte[]> entry : bytecode.entrySet()) {
                 final String className = entry.getKey();
@@ -581,18 +520,7 @@
                     continue;
                 }
                 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);
-                    }
-                }
+                unit.initializeFunctionsCode();
             }
 
             if (log.isEnabled()) {
@@ -612,18 +540,16 @@
                 log.fine(sb.toString());
             }
 
-            return setStates(fn.setRootClass(null, rootClass), BYTECODE_INSTALLED);
+            return fn.setRootClass(null, rootClass);
         }
 
         @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;
+    static final CompilationPhase INSTALL_PHASE = new InstallPhase();
 
     /** start time of transform - used for timing, see {@link jdk.nashorn.internal.runtime.Timing} */
     private long startTime;
@@ -634,21 +560,7 @@
     /** boolean that is true upon transform completion */
     private boolean isFinished;
 
-    private CompilationPhase(final EnumSet<CompilationState> pre) {
-        this.pre = pre;
-    }
-
-    private static FunctionNode setStates(final FunctionNode functionNode, final CompilationState state) {
-        if (!AssertsEnabled.assertsEnabled()) {
-            return functionNode;
-        }
-        return transformFunction(functionNode, new NodeVisitor<LexicalContext>(new LexicalContext()) {
-            @Override
-            public Node leaveFunctionNode(final FunctionNode fn) {
-                return fn.setState(lc, state);
-           }
-        });
-    }
+    private CompilationPhase() {}
 
     /**
      * Start a compilation phase
@@ -658,23 +570,7 @@
      */
     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();
+        startTime = System.nanoTime();
 
          return functionNode;
      }
@@ -709,7 +605,7 @@
     abstract FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode functionNode) throws CompilationException;
 
     /**
-     * Apply a transform to a function node, returning the transfored function node. If the transform is not
+     * Apply a transform to a function node, returning the transformed 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.
diff --git a/src/jdk/nashorn/internal/codegen/CompileUnit.java b/src/jdk/nashorn/internal/codegen/CompileUnit.java
index 13e9d71..cb40ea5 100644
--- a/src/jdk/nashorn/internal/codegen/CompileUnit.java
+++ b/src/jdk/nashorn/internal/codegen/CompileUnit.java
@@ -26,9 +26,16 @@
 package jdk.nashorn.internal.codegen;
 
 import java.io.Serializable;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.TreeSet;
 import jdk.nashorn.internal.ir.CompileUnitHolder;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 
 /**
   * Used to track split class compilation. Note that instances of the class are serializable, but all fields are
@@ -49,6 +56,8 @@
 
     private transient Class<?> clazz;
 
+    private transient Map<FunctionNode, RecompilableScriptFunctionData> functions = new IdentityHashMap<>();
+
     private transient boolean isUsed;
 
     private static int emittedUnitCount;
@@ -113,13 +122,38 @@
      * @param clazz class with code for this compile unit
      */
     void setCode(final Class<?> clazz) {
-        clazz.getClass(); // null check
-        this.clazz = clazz;
+        this.clazz = Objects.requireNonNull(clazz);
         // Revisit this - refactor to avoid null-ed out non-final fields
         // null out emitter
         this.classEmitter = null;
     }
 
+    void addFunctionInitializer(final RecompilableScriptFunctionData data, final FunctionNode functionNode) {
+        functions.put(functionNode, data);
+    }
+
+    /**
+     * Returns true if this compile unit is responsible for initializing the specified function data with specified
+     * function node.
+     * @param data the function data to check
+     * @param functionNode the function node to check
+     * @return true if this unit is responsible for initializing the function data with the function node, otherwise
+     * false
+     */
+    public boolean isInitializing(final RecompilableScriptFunctionData data, final FunctionNode functionNode) {
+        return functions.get(functionNode) == data;
+    }
+
+    void initializeFunctionsCode() {
+        for(final Map.Entry<FunctionNode, RecompilableScriptFunctionData> entry : functions.entrySet()) {
+            entry.getValue().initializeCode(entry.getKey());
+        }
+    }
+
+    Collection<FunctionNode> getFunctionNodes() {
+        return Collections.unmodifiableCollection(functions.keySet());
+    }
+
     /**
      * Add weight to this compile unit
      * @param w weight to add
diff --git a/src/jdk/nashorn/internal/codegen/Compiler.java b/src/jdk/nashorn/internal/codegen/Compiler.java
index 740022b..3a808d1 100644
--- a/src/jdk/nashorn/internal/codegen/Compiler.java
+++ b/src/jdk/nashorn/internal/codegen/Compiler.java
@@ -46,6 +46,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Consumer;
 import java.util.logging.Level;
@@ -101,9 +102,9 @@
 
     private final ConstantData constantData;
 
-    private final CodeInstaller<ScriptEnvironment> installer;
+    private final CodeInstaller installer;
 
-    /** logger for compiler, trampolines, splits and related code generation events
+    /** logger for compiler, trampolines and related code generation events
      *  that affect classes */
     private final DebugLogger log;
 
@@ -160,42 +161,40 @@
      */
     private static final int COMPILE_UNIT_NAME_BUFFER_SIZE = 32;
 
-    private final Map<Integer, byte[]> serializedAsts = new HashMap<>();
-
     /**
      * Compilation phases that a compilation goes through
      */
     public static class CompilationPhases implements Iterable<CompilationPhase> {
 
         /**
-         * Singleton that describes compilation up to the phase where a function can be serialized.
+         * Singleton that describes compilation up to the phase where a function can be cached.
          */
-        private final static CompilationPhases COMPILE_UPTO_SERIALIZABLE = new CompilationPhases(
+        private final static CompilationPhases COMPILE_UPTO_CACHED = new CompilationPhases(
                 "Common initial phases",
                 CompilationPhase.CONSTANT_FOLDING_PHASE,
                 CompilationPhase.LOWERING_PHASE,
-                CompilationPhase.TRANSFORM_BUILTINS_PHASE,
+                CompilationPhase.APPLY_SPECIALIZATION_PHASE,
                 CompilationPhase.SPLITTING_PHASE,
                 CompilationPhase.PROGRAM_POINT_PHASE,
-                CompilationPhase.SERIALIZE_SPLIT_PHASE
-                );
-
-        private final static CompilationPhases COMPILE_SERIALIZABLE_UPTO_BYTECODE = new CompilationPhases(
-                "After common phases, before bytecode generator",
                 CompilationPhase.SYMBOL_ASSIGNMENT_PHASE,
                 CompilationPhase.SCOPE_DEPTH_COMPUTATION_PHASE,
+                CompilationPhase.CACHE_AST_PHASE
+                );
+
+        private final static CompilationPhases COMPILE_CACHED_UPTO_BYTECODE = new CompilationPhases(
+                "After common phases, before bytecode generator",
                 CompilationPhase.OPTIMISTIC_TYPE_ASSIGNMENT_PHASE,
                 CompilationPhase.LOCAL_VARIABLE_TYPE_CALCULATION_PHASE
                 );
 
         /**
-         * Singleton that describes additional steps to be taken after deserializing, all the way up to (but not
-         * including) generating and installing code.
+         * Singleton that describes additional steps to be taken after retrieving a cached function, all the
+         * way up to (but not including) generating and installing code.
          */
-        public final static CompilationPhases RECOMPILE_SERIALIZED_UPTO_BYTECODE = new CompilationPhases(
-                "Recompile serialized function up to bytecode",
-                CompilationPhase.REINITIALIZE_SERIALIZED,
-                COMPILE_SERIALIZABLE_UPTO_BYTECODE
+        public final static CompilationPhases RECOMPILE_CACHED_UPTO_BYTECODE = new CompilationPhases(
+                "Recompile cached function up to bytecode",
+                CompilationPhase.REINITIALIZE_CACHED,
+                COMPILE_CACHED_UPTO_BYTECODE
                 );
 
         /**
@@ -211,8 +210,8 @@
         /** Singleton that describes compilation up to the CodeGenerator, but not actually generating code */
         public final static CompilationPhases COMPILE_UPTO_BYTECODE = new CompilationPhases(
                 "Compile upto bytecode",
-                COMPILE_UPTO_SERIALIZABLE,
-                COMPILE_SERIALIZABLE_UPTO_BYTECODE);
+                COMPILE_UPTO_CACHED,
+                COMPILE_CACHED_UPTO_BYTECODE);
 
         /** Singleton that describes a standard eager compilation, but no installation, for example used by --compile-only */
         public final static CompilationPhases COMPILE_ALL_NO_INSTALL = new CompilationPhases(
@@ -227,9 +226,9 @@
                 GENERATE_BYTECODE_AND_INSTALL);
 
         /** Singleton that describes a full compilation - this includes code installation - from serialized state*/
-        public final static CompilationPhases COMPILE_ALL_SERIALIZED = new CompilationPhases(
+        public final static CompilationPhases COMPILE_ALL_CACHED = new CompilationPhases(
                 "Eager compilation from serializaed state",
-                RECOMPILE_SERIALIZED_UPTO_BYTECODE,
+                RECOMPILE_CACHED_UPTO_BYTECODE,
                 GENERATE_BYTECODE_AND_INSTALL);
 
         /**
@@ -248,9 +247,9 @@
                 GENERATE_BYTECODE_AND_INSTALL_RESTOF);
 
         /** Compile from serialized for a rest of method */
-        public final static CompilationPhases COMPILE_SERIALIZED_RESTOF = new CompilationPhases(
+        public final static CompilationPhases COMPILE_CACHED_RESTOF = new CompilationPhases(
                 "Compile serialized, rest of",
-                RECOMPILE_SERIALIZED_UPTO_BYTECODE,
+                RECOMPILE_CACHED_UPTO_BYTECODE,
                 GENERATE_BYTECODE_AND_INSTALL_RESTOF);
 
         private final List<CompilationPhase> phases;
@@ -313,7 +312,7 @@
         }
 
         boolean isRestOfCompilation() {
-            return this == COMPILE_ALL_RESTOF || this == GENERATE_BYTECODE_AND_INSTALL_RESTOF || this == COMPILE_SERIALIZED_RESTOF;
+            return this == COMPILE_ALL_RESTOF || this == GENERATE_BYTECODE_AND_INSTALL_RESTOF || this == COMPILE_CACHED_RESTOF;
         }
 
         String getDesc() {
@@ -353,47 +352,83 @@
     private static final AtomicInteger COMPILATION_ID = new AtomicInteger(0);
 
     /**
-     * Constructor
+     * Creates a new compiler instance for initial compilation of a script.
      *
-     * @param context   context
-     * @param env       script environment
      * @param installer code installer
      * @param source    source to compile
      * @param errors    error manager
      * @param isStrict  is this a strict compilation
+     * @return a new compiler
      */
-    public Compiler(
-            final Context context,
-            final ScriptEnvironment env,
-            final CodeInstaller<ScriptEnvironment> installer,
+    public static Compiler forInitialCompilation(
+            final CodeInstaller installer,
             final Source source,
             final ErrorManager errors,
             final boolean isStrict) {
-        this(context, env, installer, source, errors, isStrict, false, null, null, null, null, null, null);
+        return new Compiler(installer.getContext(), installer, source, errors, isStrict);
     }
 
     /**
-     * Constructor
+     * Creates a compiler without a code installer. It can only be used to compile code, not install the
+     * generated classes and as such it is useful only for implementation of {@code --compile-only} command
+     * line option.
+     * @param context  the current context
+     * @param source   source to compile
+     * @param isStrict is this a strict compilation
+     * @return a new compiler
+     */
+    public static Compiler forNoInstallerCompilation(
+            final Context context,
+            final Source source,
+            final boolean isStrict) {
+        return new Compiler(context, null, source, context.getErrorManager(), isStrict);
+    }
+
+    /**
+     * Creates a compiler for an on-demand compilation job.
      *
-     * @param context                  context
-     * @param env                      script environment
      * @param installer                code installer
      * @param source                   source to compile
-     * @param errors                   error manager
      * @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}
+     * @return a new compiler
      */
-    @SuppressWarnings("unused")
-    public Compiler(
+    public static Compiler forOnDemandCompilation(
+            final CodeInstaller installer,
+            final Source source,
+            final boolean isStrict,
+            final RecompilableScriptFunctionData compiledFunction,
+            final TypeMap types,
+            final Map<Integer, Type> invalidatedProgramPoints,
+            final Object typeInformationFile,
+            final int[] continuationEntryPoints,
+            final ScriptObject runtimeScope) {
+        final Context context = installer.getContext();
+        return new Compiler(context, installer, source, context.getErrorManager(), isStrict, true,
+                compiledFunction, types, invalidatedProgramPoints, typeInformationFile,
+                continuationEntryPoints, runtimeScope);
+    }
+
+    /**
+     * Convenience constructor for non on-demand compiler instances.
+     */
+    private Compiler(
             final Context context,
-            final ScriptEnvironment env,
-            final CodeInstaller<ScriptEnvironment> installer,
+            final CodeInstaller installer,
+            final Source source,
+            final ErrorManager errors,
+            final boolean isStrict) {
+        this(context, installer, source, errors, isStrict, false, null, null, null, null, null, null);
+    }
+
+    private Compiler(
+            final Context context,
+            final CodeInstaller installer,
             final Source source,
             final ErrorManager errors,
             final boolean isStrict,
@@ -405,7 +440,7 @@
             final int[] continuationEntryPoints,
             final ScriptObject runtimeScope) {
         this.context                  = context;
-        this.env                      = env;
+        this.env                      = context.getEnv();
         this.installer                = installer;
         this.constantData             = new ConstantData();
         this.compileUnits             = CompileUnit.createCompileUnitSet();
@@ -427,7 +462,7 @@
         this.optimistic = env._optimistic_types;
     }
 
-    private static String safeSourceName(final ScriptEnvironment env, final CodeInstaller<ScriptEnvironment> installer, final Source source) {
+    private String safeSourceName() {
         String baseName = new File(source.getName()).getName();
 
         final int index = baseName.lastIndexOf(".js");
@@ -486,7 +521,7 @@
             sb.append('$');
         }
 
-        sb.append(Compiler.safeSourceName(env, installer, source));
+        sb.append(safeSourceName());
 
         return sb.toString();
     }
@@ -565,7 +600,7 @@
      * @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);
+        return invalidatedProgramPoints.isEmpty() ? null : new TreeMap<>(invalidatedProgramPoints);
     }
 
     TypeMap getTypeMap() {
@@ -607,7 +642,7 @@
             newFunctionNode.uniqueName(reservedName);
         }
 
-        final boolean info = log.levelFinerThanOrEqual(Level.INFO);
+        final boolean info = log.isLoggable(Level.INFO);
 
         final DebugLogger timeLogger = env.isTimingEnabled() ? env._timing.getLogger() : null;
 
@@ -644,12 +679,12 @@
         if (info) {
             final StringBuilder sb = new StringBuilder("<< Finished compile job for ");
             sb.append(newFunctionNode.getSource()).
-                append(':').
-                append(quote(newFunctionNode.getName()));
+            append(':').
+            append(quote(newFunctionNode.getName()));
 
             if (time > 0L && timeLogger != null) {
                 assert env.isTimingEnabled();
-                sb.append(" in ").append(time).append(" ms");
+                sb.append(" in ").append(TimeUnit.NANOSECONDS.toMillis(time)).append(" ms");
             }
             log.info(sb);
         }
@@ -685,7 +720,7 @@
         return constantData;
     }
 
-    CodeInstaller<ScriptEnvironment> getCodeInstaller() {
+    CodeInstaller getCodeInstaller() {
         return installer;
     }
 
@@ -704,21 +739,6 @@
         return sb.toString();
     }
 
-    Map<Integer, FunctionInitializer> functionInitializers;
-
-    void addFunctionInitializer(final RecompilableScriptFunctionData functionData, final FunctionNode functionNode) {
-        if (functionInitializers == null) {
-            functionInitializers = new HashMap<>();
-        }
-        if (!functionInitializers.containsKey(functionData)) {
-            functionInitializers.put(functionData.getFunctionNodeId(), new FunctionInitializer(functionNode));
-        }
-    }
-
-    Map<Integer, FunctionInitializer> getFunctionInitializers() {
-        return functionInitializers;
-    }
-
     /**
      * Persist current compilation with the given {@code cacheKey}.
      * @param cacheKey cache key
@@ -726,15 +746,17 @@
      */
     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);
+            final Map<Integer, FunctionInitializer> initializers = new HashMap<>();
+            if (isOnDemandCompilation()) {
+                initializers.put(functionNode.getId(), new FunctionInitializer(functionNode, getInvalidatedProgramPoints()));
             } else {
-                initializers = functionInitializers;
+                for (final CompileUnit compileUnit : getCompileUnits()) {
+                    for (final FunctionNode fn : compileUnit.getFunctionNodes()) {
+                        initializers.put(fn.getId(), new FunctionInitializer(fn));
+                    }
+                }
             }
             final String mainClassName = getFirstCompileUnit().getUnitClassName();
             installer.storeScript(cacheKey, source, mainClassName, bytecode, initializers, constantData.toArray(), compilationId);
@@ -779,14 +801,6 @@
         compileUnits.addAll(newUnits);
     }
 
-    void serializeAst(final FunctionNode fn) {
-        serializedAsts.put(fn.getId(), AstSerializer.serialize(fn));
-    }
-
-    byte[] removeSerializedAst(final int fnId) {
-        return serializedAsts.remove(fnId);
-    }
-
     CompileUnit findUnit(final long weight) {
         for (final CompileUnit unit : compileUnits) {
             if (unit.canHold(weight)) {
@@ -842,9 +856,9 @@
         final long                        totalSize = osc.calculateObjectSize(functionNode);
 
         sb.append(phaseName).
-            append(" Total size = ").
-            append(totalSize / 1024 / 1024).
-            append("MB");
+        append(" Total size = ").
+        append(totalSize / 1024 / 1024).
+        append("MB");
         log.info(sb);
 
         Collections.sort(list, new Comparator<ClassHistogramElement>() {
diff --git a/src/jdk/nashorn/internal/codegen/CompilerConstants.java b/src/jdk/nashorn/internal/codegen/CompilerConstants.java
index e84c9f0..0d64ac2 100644
--- a/src/jdk/nashorn/internal/codegen/CompilerConstants.java
+++ b/src/jdk/nashorn/internal/codegen/CompilerConstants.java
@@ -149,8 +149,11 @@
     /** Arguments parameter in scope object constructors; in slot 3 when present */
     INIT_ARGUMENTS(null, 3),
 
-    /** prefix for all ScriptObject subclasses with fields, @see ObjectGenerator */
-    JS_OBJECT_PREFIX("JO"),
+    /** prefix for all ScriptObject subclasses with dual object/primitive fields, see {@link ObjectClassGenerator} */
+    JS_OBJECT_DUAL_FIELD_PREFIX("JD"),
+
+    /** prefix for all ScriptObject subclasses with object fields only, see {@link ObjectClassGenerator} */
+    JS_OBJECT_SINGLE_FIELD_PREFIX("JO"),
 
     /** name for allocate method in JO objects */
     ALLOCATE("allocate"),
@@ -189,7 +192,7 @@
     private static Set<String> symbolNames;
 
     /**
-     * Prefix used for internal methods generated in script clases.
+     * Prefix used for internal methods generated in script classes.
      */
     private static final String INTERNAL_METHOD_PREFIX = ":";
 
@@ -222,7 +225,7 @@
     }
 
     /**
-     * Check whether a name is that of a reserved compiler constnat
+     * Check whether a name is that of a reserved compiler constant
      * @param name name
      * @return true if compiler constant name
      */
diff --git a/src/jdk/nashorn/internal/codegen/ConstantData.java b/src/jdk/nashorn/internal/codegen/ConstantData.java
index cd87f0f..a7e6653 100644
--- a/src/jdk/nashorn/internal/codegen/ConstantData.java
+++ b/src/jdk/nashorn/internal/codegen/ConstantData.java
@@ -30,6 +30,8 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
+
 import jdk.nashorn.internal.runtime.PropertyMap;
 
 /**
@@ -120,7 +122,7 @@
         private final int hashCode;
 
         public PropertyMapWrapper(final PropertyMap map) {
-            this.hashCode = Arrays.hashCode(map.getProperties());
+            this.hashCode = Arrays.hashCode(map.getProperties()) + 31 * Objects.hashCode(map.getClassName());
             this.propertyMap = map;
         }
 
@@ -131,8 +133,13 @@
 
         @Override
         public boolean equals(final Object other) {
-            return other instanceof PropertyMapWrapper &&
-                    Arrays.equals(propertyMap.getProperties(), ((PropertyMapWrapper) other).propertyMap.getProperties());
+            if (!(other instanceof PropertyMapWrapper)) {
+                return false;
+            }
+            final PropertyMap otherMap = ((PropertyMapWrapper) other).propertyMap;
+            return propertyMap == otherMap
+                    || (Arrays.equals(propertyMap.getProperties(), otherMap.getProperties())
+                        && Objects.equals(propertyMap.getClassName(), otherMap.getClassName()));
         }
     }
 
diff --git a/src/jdk/nashorn/internal/codegen/DumpBytecode.java b/src/jdk/nashorn/internal/codegen/DumpBytecode.java
index e677382..620a43e 100644
--- a/src/jdk/nashorn/internal/codegen/DumpBytecode.java
+++ b/src/jdk/nashorn/internal/codegen/DumpBytecode.java
@@ -88,7 +88,7 @@
             }
 
 
-            // should code be dumped to disk - only valid in compile_only mode?
+            // should code be dumped to disk
             if (env._dest_dir != null) {
                 final String fileName = className.replace('.', File.separatorChar) + ".class";
                 final int    index    = fileName.lastIndexOf(File.separatorChar);
diff --git a/src/jdk/nashorn/internal/codegen/Emitter.java b/src/jdk/nashorn/internal/codegen/Emitter.java
deleted file mode 100644
index b9feeeb..0000000
--- a/src/jdk/nashorn/internal/codegen/Emitter.java
+++ /dev/null
@@ -1,49 +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;
-
-/**
- * Interface for anything that interacts with a low level bytecode
- * generation module, for example ASM.
- * <p>
- * This is pretty generic, i.e. it can be a ClassEmitter, MethodEmitter
- * or potentially even more fine grained stuff.
- *
- */
-public interface Emitter {
-
-    /**
-     * Register the start of emission for this CodeEmitter
-     */
-    public void begin();
-
-    /**
-     * Register the end of emission for this CodeEmitter.
-     * This is typically required before generated code can
-     * be requested from it
-     */
-    public void end();
-}
diff --git a/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java b/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java
index 491af86..9aa6465 100644
--- a/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java
+++ b/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java
@@ -34,7 +34,6 @@
 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
 
-import java.util.Iterator;
 import java.util.List;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.Symbol;
@@ -91,27 +90,20 @@
         findClass();
     }
 
-    /**
-     * Construct an object.
-     *
-     * @param method the method emitter
-     */
     @Override
-    protected void makeObject(final MethodEmitter method) {
+    public void createObject(final MethodEmitter method) {
         makeMap();
         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);
-        }
+        // 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.
+        assert fieldObjectClass != null;
+        method._new(fieldObjectClass).dup();
+
         loadMap(method); //load the map
 
         if (isScope()) {
@@ -126,16 +118,19 @@
         } else {
             method.invoke(constructorNoLookup(className, PropertyMap.class));
         }
+    }
 
+    @Override
+    public void populateRange(final MethodEmitter method, final Type objectType, final int objectSlot, final int start, final int end) {
+        method.load(objectType, objectSlot);
         // Set values.
-        final Iterator<MapTuple<T>> iter = tuples.iterator();
-
-        while (iter.hasNext()) {
-            final MapTuple<T> tuple = iter.next();
+        for (int i = start; i < end; i++) {
+            final MapTuple<T> tuple = tuples.get(i);
             //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);
+                method.dup();
                 if (!isValidArrayIndex(index)) {
                     putField(method, tuple.key, tuple.symbol.getFieldIndex(), tuple);
                 } else {
@@ -151,7 +146,7 @@
     @Override
     protected PropertyMap makeMap() {
         assert propertyMap == null : "property map already initialized";
-        propertyMap = newMapCreator(fieldObjectClass).makeFieldMap(hasArguments(), fieldCount, paddedFieldCount, evalCode);
+        propertyMap = newMapCreator(fieldObjectClass).makeFieldMap(hasArguments(), codegen.useDualFields(), fieldCount, paddedFieldCount, evalCode);
         return propertyMap;
     }
 
@@ -164,9 +159,7 @@
      * @param tuple       Tuple to store.
      */
     private void putField(final MethodEmitter method, final String key, final int fieldIndex, final MapTuple<T> tuple) {
-        method.dup();
-
-        final Type    fieldType   = tuple.isPrimitive() ? PRIMITIVE_FIELD_TYPE : Type.OBJECT;
+        final Type    fieldType   = codegen.useDualFields() && tuple.isPrimitive() ? PRIMITIVE_FIELD_TYPE : Type.OBJECT;
         final String  fieldClass  = getClassName();
         final String  fieldName   = getFieldName(fieldIndex, fieldType);
         final String  fieldDesc   = typeDescriptor(fieldType.getTypeClass());
@@ -187,7 +180,6 @@
      * @param tuple  Tuple to store.
      */
     private void putSlot(final MethodEmitter method, final long index, final MapTuple<T> tuple) {
-        method.dup();
         if (JSType.isRepresentableAsInt(index)) {
             method.load((int)index);
         } else {
@@ -202,8 +194,8 @@
      */
     private void findClass() {
         fieldObjectClassName = isScope() ?
-                ObjectClassGenerator.getClassName(fieldCount, paramCount) :
-                ObjectClassGenerator.getClassName(paddedFieldCount);
+                ObjectClassGenerator.getClassName(fieldCount, paramCount, codegen.useDualFields()) :
+                ObjectClassGenerator.getClassName(paddedFieldCount, codegen.useDualFields());
 
         try {
             this.fieldObjectClass = Context.forStructureClass(Compiler.binaryName(fieldObjectClassName));
@@ -212,6 +204,11 @@
         }
     }
 
+    @Override
+    protected Class<? extends ScriptObject> getAllocatorClass() {
+        return fieldObjectClass;
+    }
+
     /**
      * Get the class name for the object class,
      * e.g. {@code com.nashorn.oracle.scripts.JO2P0}
diff --git a/src/jdk/nashorn/internal/codegen/FindScopeDepths.java b/src/jdk/nashorn/internal/codegen/FindScopeDepths.java
index 431244d..bcdf73f 100644
--- a/src/jdk/nashorn/internal/codegen/FindScopeDepths.java
+++ b/src/jdk/nashorn/internal/codegen/FindScopeDepths.java
@@ -32,16 +32,14 @@
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
-import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor;
 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.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
@@ -55,7 +53,7 @@
  * FunctionNode being compiled
  */
 @Logger(name="scopedepths")
-final class FindScopeDepths extends NodeVisitor<LexicalContext> implements Loggable {
+final class FindScopeDepths extends SimpleNodeVisitor implements Loggable {
 
     private final Compiler compiler;
     private final Map<Integer, Map<Integer, RecompilableScriptFunctionData>> fnIdToNestedFunctions = new HashMap<>();
@@ -68,7 +66,6 @@
     private int dynamicScopeCount;
 
     FindScopeDepths(final Compiler compiler) {
-        super(new LexicalContext());
         this.compiler = compiler;
         this.log      = initLogger(compiler.getContext());
     }
@@ -183,14 +180,16 @@
     @Override
     public Node leaveFunctionNode(final FunctionNode functionNode) {
         final String name = functionNode.getName();
-        FunctionNode newFunctionNode = functionNode.setState(lc, CompilationState.SCOPE_DEPTHS_COMPUTED);
-
+        FunctionNode newFunctionNode = functionNode;
         if (compiler.isOnDemandCompilation()) {
             final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(newFunctionNode.getId());
             if (data.inDynamicContext()) {
                 log.fine("Reviving scriptfunction ", quote(name), " as defined in previous (now lost) dynamic scope.");
                 newFunctionNode = newFunctionNode.setInDynamicContext(lc);
             }
+            if (newFunctionNode == lc.getOutermostFunction() && !newFunctionNode.hasApplyToCallSpecialization()) {
+                data.setCachedAst(newFunctionNode);
+            }
             return newFunctionNode;
         }
 
@@ -208,11 +207,10 @@
         final RecompilableScriptFunctionData data = new RecompilableScriptFunctionData(
                 newFunctionNode,
                 compiler.getCodeInstaller(),
-                new AllocatorDescriptor(newFunctionNode.getThisProperties()),
+                ObjectClassGenerator.createAllocationStrategy(newFunctionNode.getThisProperties(), compiler.getContext().useDualFields()),
                 nestedFunctions,
                 externalSymbolDepths.get(fnId),
-                internalSymbols.get(fnId),
-                compiler.removeSerializedAst(fnId));
+                internalSymbols.get(fnId));
 
         if (lc.getOutermostFunction() != newFunctionNode) {
             final FunctionNode parentFn = lc.getParentFunction(newFunctionNode);
@@ -276,17 +274,13 @@
 
         //get all symbols that are referenced inside this function body
         final Set<Symbol> symbols = new HashSet<>();
-        block.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        block.accept(new SimpleNodeVisitor() {
             @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);
-                        }
-                    }
+            public boolean enterIdentNode(final IdentNode identNode) {
+                final Symbol symbol = identNode.getSymbol();
+                if (symbol != null && symbol.isScope()) {
+                    //if this is an internal symbol, skip it.
+                    symbols.add(symbol);
                 }
                 return true;
             }
diff --git a/src/jdk/nashorn/internal/codegen/FoldConstants.java b/src/jdk/nashorn/internal/codegen/FoldConstants.java
index 092b788..e72ea03 100644
--- a/src/jdk/nashorn/internal/codegen/FoldConstants.java
+++ b/src/jdk/nashorn/internal/codegen/FoldConstants.java
@@ -37,9 +37,7 @@
 import jdk.nashorn.internal.ir.EmptyNode;
 import jdk.nashorn.internal.ir.Expression;
 import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
 import jdk.nashorn.internal.ir.IfNode;
-import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
 import jdk.nashorn.internal.ir.Node;
@@ -48,7 +46,7 @@
 import jdk.nashorn.internal.ir.TernaryNode;
 import jdk.nashorn.internal.ir.UnaryNode;
 import jdk.nashorn.internal.ir.VarNode;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
@@ -60,12 +58,11 @@
  * Simple constant folding pass, executed before IR is starting to be lowered.
  */
 @Logger(name="fold")
-final class FoldConstants extends NodeVisitor<LexicalContext> implements Loggable {
+final class FoldConstants extends SimpleNodeVisitor implements Loggable {
 
     private final DebugLogger log;
 
     FoldConstants(final Compiler compiler) {
-        super(new LexicalContext());
         this.log = initLogger(compiler.getContext());
     }
 
@@ -101,7 +98,7 @@
 
     @Override
     public Node leaveFunctionNode(final FunctionNode functionNode) {
-        return functionNode.setState(lc, CompilationState.CONSTANT_FOLDED);
+        return functionNode;
     }
 
     @Override
@@ -117,7 +114,7 @@
                 statements.addAll(executed.getStatements()); // Get statements form executed branch
             }
             if (dropped != null) {
-                extractVarNodes(dropped, statements); // Get var-nodes from non-executed branch
+                extractVarNodesFromDeadCode(dropped, statements); // Get var-nodes from non-executed branch
             }
             if (statements.isEmpty()) {
                 return new EmptyNode(ifNode);
@@ -186,14 +183,27 @@
         protected abstract LiteralNode<?> eval();
     }
 
-    private static void extractVarNodes(final Block block, final List<Statement> statements) {
-        final LexicalContext lc = new LexicalContext();
-        block.accept(lc, new NodeVisitor<LexicalContext>(lc) {
+    /**
+     * When we eliminate dead code, we must preserve var declarations as they are scoped to the whole
+     * function. This method gathers var nodes from code passed to it, removing their initializers.
+     *
+     * @param deadCodeRoot the root node of eliminated dead code
+     * @param statements a list that will be receiving the var nodes from the dead code, with their
+     * initializers removed.
+     */
+    static void extractVarNodesFromDeadCode(final Node deadCodeRoot, final List<Statement> statements) {
+        deadCodeRoot.accept(new SimpleNodeVisitor() {
             @Override
             public boolean enterVarNode(final VarNode varNode) {
                 statements.add(varNode.setInit(null));
                 return false;
             }
+
+            @Override
+            public boolean enterFunctionNode(final FunctionNode functionNode) {
+                // Don't descend into nested functions
+                return false;
+            }
         });
     }
 
@@ -353,8 +363,8 @@
                 return null;
             }
 
-            isInteger &= JSType.isRepresentableAsInt(value) && !JSType.isNegativeZero(value);
-            isLong    &= JSType.isRepresentableAsLong(value) && !JSType.isNegativeZero(value);
+            isInteger &= JSType.isStrictlyRepresentableAsInt(value);
+            isLong    &= JSType.isStrictlyRepresentableAsLong(value);
 
             if (isInteger) {
                 return LiteralNode.newInstance(token, finish, (int)value);
diff --git a/src/jdk/nashorn/internal/codegen/Label.java b/src/jdk/nashorn/internal/codegen/Label.java
index e4b0249..a70165d 100644
--- a/src/jdk/nashorn/internal/codegen/Label.java
+++ b/src/jdk/nashorn/internal/codegen/Label.java
@@ -333,7 +333,7 @@
          * @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
+         * @param type the type written to the slot
          */
         void onLocalStore(final Type type, final int slot, final boolean onlySymbolLiveValue) {
             if(onlySymbolLiveValue) {
@@ -447,7 +447,7 @@
             undefineLocalVariables(liveLocalCount, true);
             // Temporaries are promoted
             firstTemp = liveLocalCount;
-            // No trailing undefineds
+            // No trailing undefined values
             localVariableTypes.subList(firstTemp, localVariableTypes.size()).clear();
             assert symbolBoundary.length() == firstTemp;
             // Generalize all reference types to Object, and promote boolean to int
@@ -497,7 +497,7 @@
     private transient Label.Stack stack;
 
     /** ASM representation of this label */
-    private jdk.internal.org.objectweb.asm.Label label;
+    private transient jdk.internal.org.objectweb.asm.Label label;
 
     /** Id for debugging purposes, remove if footprint becomes unmanageable */
     private final int id;
diff --git a/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java b/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java
index ac3c293..c7f0800 100644
--- a/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java
+++ b/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java
@@ -40,34 +40,37 @@
 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.CallNode;
 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.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.GetSplitState;
 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.JumpToInlinedFinally;
 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.LocalVariableConversion;
 import jdk.nashorn.internal.ir.LoopNode;
 import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.ObjectNode;
 import jdk.nashorn.internal.ir.PropertyNode;
 import jdk.nashorn.internal.ir.ReturnNode;
 import jdk.nashorn.internal.ir.RuntimeNode;
@@ -82,7 +85,9 @@
 import jdk.nashorn.internal.ir.UnaryNode;
 import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.WhileNode;
+import jdk.nashorn.internal.ir.WithNode;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.parser.TokenType;
 
 /**
@@ -101,7 +106,7 @@
  * instances of the calculator to be run on nested functions (when not lazy compiling).
  *
  */
-final class LocalVariableTypesCalculator extends NodeVisitor<LexicalContext>{
+final class LocalVariableTypesCalculator extends SimpleNodeVisitor {
 
     private static class JumpOrigin {
         final JoinPredecessor node;
@@ -131,8 +136,44 @@
         OBJECT(Type.OBJECT);
 
         private final Type type;
+        private final TypeHolderExpression typeExpression;
+
         private LvarType(final Type type) {
             this.type = type;
+            this.typeExpression = new TypeHolderExpression(type);
+        }
+    }
+
+    /**
+     * A bogus Expression subclass that only reports its type. Used to interrogate BinaryNode and UnaryNode about their
+     * types by creating temporary copies of them and replacing their operands with instances of these. An alternative
+     * solution would be to add BinaryNode.getType(Type lhsType, Type rhsType) and UnaryNode.getType(Type exprType)
+     * methods. For the time being though, this is easier to implement and is in fact fairly clean. It does result in
+     * generation of higher number of temporary short lived nodes, though.
+     */
+    private static class TypeHolderExpression extends Expression {
+        private static final long serialVersionUID = 1L;
+
+        private final Type type;
+
+        TypeHolderExpression(final Type type) {
+            super(0L, 0, 0);
+            this.type = type;
+        }
+
+        @Override
+        public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+            throw new AssertionError();
+        }
+
+        @Override
+        public Type getType() {
+            return type;
+        }
+
+        @Override
+        public void toString(final StringBuilder sb, final boolean printType) {
+            throw new AssertionError();
         }
     }
 
@@ -165,7 +206,6 @@
         // 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);
     }
 
@@ -188,7 +228,7 @@
             for(final Symbol symbol: commonSymbols) {
                 final LvarType type1 = types1.get(symbol);
                 final LvarType type2 = types2.get(symbol);
-                final LvarType widest = widestLvarType(type1,  type2);
+                final LvarType widest = widestLvarType(type1, type2);
                 if(widest != type1 && matches1) {
                     matches1 = false;
                     if(!matches2) {
@@ -201,7 +241,7 @@
                         union = cloneMap(types2);
                     }
                 }
-                if(!(matches1 || matches2) && union != null) { //remove overly enthusiastic "union can be null" warning
+                if(!(matches1 || matches2)) {
                     assert union != null;
                     union.put(symbol, widest);
                 }
@@ -359,6 +399,8 @@
     // 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<>();
+    // Stack for evaluated expression types.
+    private final Deque<LvarType> typeStack = new ArrayDeque<>();
 
     // Whether the current point in the AST is reachable code
     private boolean reachable = true;
@@ -375,8 +417,6 @@
     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
@@ -386,7 +426,6 @@
     private final Deque<Label> catchLabels = new ArrayDeque<>();
 
     LocalVariableTypesCalculator(final Compiler compiler) {
-        super(new LexicalContext());
         this.compiler = compiler;
     }
 
@@ -400,62 +439,56 @@
     private void doesNotContinueSequentially() {
         reachable = false;
         localVariableTypes = Collections.emptyMap();
+        assertTypeStackIsEmpty();
     }
 
+    private boolean pushExpressionType(final Expression expr) {
+        typeStack.push(toLvarType(expr.getType()));
+        return false;
+    }
+
+    @Override
+    public boolean enterAccessNode(final AccessNode accessNode) {
+        visitExpression(accessNode.getBase());
+        return pushExpressionType(accessNode);
+    }
 
     @Override
     public boolean enterBinaryNode(final BinaryNode binaryNode) {
         // NOTE: regardless of operator's lexical associativity, lhs is always evaluated first.
         final Expression lhs = binaryNode.lhs();
-        final boolean isAssignment = binaryNode.isAssignment();
-        LvarType lhsTypeOnLoad = null;
-        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()) {
-                    final IdentNode ident = ((IdentNode)lhs);
-                    ident.accept(this);
-                    // Self-assignment can cause a change in the type of the variable. For purposes of evaluating
-                    // the type of the operation, we must use its type as it was when it was loaded. If we didn't
-                    // do this, some awkward expressions would end up being calculated incorrectly, e.g.
-                    // "var x; x += x = 0;". In this case we have undefined+int so the result type is double (NaN).
-                    // However, if we used the type of "x" on LHS after we evaluated RHS, we'd see int+int, so the
-                    // result type would be either optimistic int or pessimistic long, which would be wrong.
-                    lhsTypeOnLoad = getLocalVariableTypeIfBytecode(ident.getSymbol());
-                }
-            }
+        final LvarType lhsType;
+        if (!(lhs instanceof IdentNode && binaryNode.isTokenType(TokenType.ASSIGN))) {
+            lhsType = visitExpression(lhs);
         } else {
-            lhs.accept(this);
+            // Can't visit IdentNode on LHS of a simple assignment, as visits imply use, and this is def.
+            // The type is irrelevant, as only RHS is used to determine the type anyway.
+            lhsType = LvarType.UNDEFINED;
         }
 
         final boolean isLogical = binaryNode.isLogical();
-        assert !(isAssignment && isLogical); // there are no logical assignment operators in JS
         final Label joinLabel = isLogical ? new Label("") : null;
         if(isLogical) {
             jumpToLabel((JoinPredecessor)lhs, joinLabel);
         }
 
         final Expression rhs = binaryNode.rhs();
-        rhs.accept(this);
+        final LvarType rhsType = visitExpression(rhs);
         if(isLogical) {
             jumpToLabel((JoinPredecessor)rhs, joinLabel);
         }
         joinOnLabel(joinLabel);
 
-        if(isAssignment && lhs instanceof IdentNode) {
+        final LvarType type = toLvarType(binaryNode.setOperands(lhsType.typeExpression, rhsType.typeExpression).getType());
+
+        if(binaryNode.isAssignment() && lhs instanceof IdentNode) {
             if(binaryNode.isSelfModifying()) {
-                onSelfAssignment((IdentNode)lhs, binaryNode, lhsTypeOnLoad);
+                onSelfAssignment((IdentNode)lhs, type);
             } else {
-                onAssignment((IdentNode)lhs, rhs);
+                onAssignment((IdentNode)lhs, type);
             }
         }
+        typeStack.push(type);
         return false;
     }
 
@@ -475,6 +508,17 @@
     }
 
     @Override
+    public boolean enterCallNode(final CallNode callNode) {
+        visitExpression(callNode.getFunction());
+        visitExpressions(callNode.getArgs());
+        final CallNode.EvalArgs evalArgs = callNode.getEvalArgs();
+        if (evalArgs != null) {
+            visitExpressions(evalArgs.getArgs());
+        }
+        return pushExpressionType(callNode);
+    }
+
+    @Override
     public boolean enterContinueNode(final ContinueNode continueNode) {
         return enterJumpStatement(continueNode);
     }
@@ -483,8 +527,8 @@
         if(!reachable) {
             return false;
         }
-        final BreakableNode target = jump.getTarget(lc);
-        jumpToLabel(jump, jump.getTargetLabel(target), getBreakTargetTypes(target));
+        assertTypeStackIsEmpty();
+        jumpToLabel(jump, jump.getTargetLabel(lc), getBreakTargetTypes(jump.getPopScopeLimit(lc)));
         doesNotContinueSequentially();
         return false;
     }
@@ -495,6 +539,7 @@
     }
 
     private void enterDoWhileLoop(final WhileNode loopNode) {
+        assertTypeStackIsEmpty();
         final JoinPredecessorExpression test = loopNode.getTest();
         final Block body = loopNode.getBody();
         final Label continueLabel = loopNode.getContinueLabel();
@@ -512,7 +557,7 @@
             if(!reachable) {
                 break;
             }
-            test.accept(this);
+            visitExpressionOnEmptyStack(test);
             jumpToLabel(test, breakLabel);
             if(isAlwaysFalse(test)) {
                 break;
@@ -535,6 +580,45 @@
     }
 
     @Override
+    public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) {
+        if (reachable) {
+            visitExpressionOnEmptyStack(expressionStatement.getExpression());
+        }
+        return false;
+    }
+
+    private void assertTypeStackIsEmpty() {
+        assert typeStack.isEmpty();
+    }
+
+    @Override
+    protected Node leaveDefault(final Node node) {
+        assert !(node instanceof Expression); // All expressions were handled
+        assert !(node instanceof Statement) || typeStack.isEmpty(); // No statements leave with a non-empty stack
+        return node;
+    }
+
+    private LvarType visitExpressionOnEmptyStack(final Expression expr) {
+        assertTypeStackIsEmpty();
+        return visitExpression(expr);
+    }
+
+    private LvarType visitExpression(final Expression expr) {
+        final int stackSize = typeStack.size();
+        expr.accept(this);
+        assert typeStack.size() == stackSize + 1;
+        return typeStack.pop();
+    }
+
+    private void visitExpressions(final List<Expression> exprs) {
+        for(final Expression expr: exprs) {
+            if (expr != null) {
+                visitExpression(expr);
+            }
+        }
+    }
+
+    @Override
     public boolean enterForNode(final ForNode forNode) {
         if(!reachable) {
             return false;
@@ -543,7 +627,7 @@
         final Expression init = forNode.getInit();
         if(forNode.isForIn()) {
             final JoinPredecessorExpression iterable = forNode.getModify();
-            iterable.accept(this);
+            visitExpression(iterable);
             enterTestFirstLoop(forNode, null, init,
                     // If we're iterating over property names, and we can discern from the runtime environment
                     // of the compilation that the object being iterated over must use strings for property
@@ -552,16 +636,18 @@
                     !compiler.useOptimisticTypes() || (!forNode.isForEach() && compiler.hasStringPropertyIterator(iterable.getExpression())));
         } else {
             if(init != null) {
-                init.accept(this);
+                visitExpressionOnEmptyStack(init);
             }
             enterTestFirstLoop(forNode, forNode.getModify(), null, false);
         }
+        assertTypeStackIsEmpty();
         return false;
     }
 
     @Override
     public boolean enterFunctionNode(final FunctionNode functionNode) {
         if(alreadyEnteredTopLevelFunction) {
+            typeStack.push(LvarType.OBJECT);
             return false;
         }
         int pos = 0;
@@ -603,79 +689,139 @@
     }
 
     @Override
+    public boolean enterGetSplitState(final GetSplitState getSplitState) {
+        return pushExpressionType(getSplitState);
+    }
+
+    @Override
     public boolean enterIdentNode(final IdentNode identNode) {
         final Symbol symbol = identNode.getSymbol();
         if(symbol.isBytecodeLocal()) {
             symbolIsUsed(symbol);
-            setIdentifierLvarType(identNode, getLocalVariableType(symbol));
+            final LvarType type = getLocalVariableType(symbol);
+            setIdentifierLvarType(identNode, type);
+            typeStack.push(type);
+        } else {
+            pushExpressionType(identNode);
         }
         return false;
     }
 
     @Override
     public boolean enterIfNode(final IfNode ifNode) {
+        processIfNode(ifNode);
+        return false;
+    }
+
+    private void processIfNode(final IfNode ifNode) {
         if(!reachable) {
-            return false;
+            return;
         }
 
         final Expression test = ifNode.getTest();
         final Block pass = ifNode.getPass();
         final Block fail = ifNode.getFail();
 
-        test.accept(this);
+        visitExpressionOnEmptyStack(test);
 
-        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);
+        final Map<Symbol, LvarType> passLvarTypes;
+        final boolean reachableFromPass;
+        final boolean isTestAlwaysTrue = isAlwaysTrue(test);
+        if(isAlwaysFalse(test)) {
+            passLvarTypes = null;
+            reachableFromPass = false;
         } else {
+            final Map<Symbol, LvarType> afterTestLvarTypes = localVariableTypes;
+            pass.accept(this);
+            assertTypeStackIsEmpty();
+            if (isTestAlwaysTrue) {
+                return;
+            }
+            passLvarTypes = localVariableTypes;
+            reachableFromPass = reachable;
             localVariableTypes = afterTestLvarTypes;
+            reachable = true;
         }
 
+        // If we get here, then we need to consider the case where pass block is not executed
+        assert !isTestAlwaysTrue;
+
+        if (fail != null) {
+            fail.accept(this);
+            assertTypeStackIsEmpty();
+        }
+
+        if(reachable) {
+            if(reachableFromPass) {
+                final Map<Symbol, LvarType> failLvarTypes = localVariableTypes;
+                localVariableTypes = getUnionTypes(passLvarTypes, failLvarTypes);
+                setConversion(pass, passLvarTypes, localVariableTypes);
+                // 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(fail != null ? fail : ifNode, failLvarTypes, localVariableTypes);
+            }
+        } else if (reachableFromPass) {
+            assert passLvarTypes != null;
+            localVariableTypes = passLvarTypes;
+            reachable = true;
+        }
+    }
+
+    @Override
+    public boolean enterIndexNode(final IndexNode indexNode) {
+        visitExpression(indexNode.getBase());
+        visitExpression(indexNode.getIndex());
+        return pushExpressionType(indexNode);
+    }
+
+    @Override
+    public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression joinExpr) {
+        final Expression expr = joinExpr.getExpression();
+        if (expr != null) {
+            expr.accept(this);
+        } else {
+            typeStack.push(LvarType.UNDEFINED);
+        }
         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);
+    public boolean enterJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+        return enterJumpStatement(jumpToInlinedFinally);
+    }
+
+    @Override
+    public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
+        if (literalNode instanceof ArrayLiteralNode) {
+            final List<Expression> expressions = ((ArrayLiteralNode)literalNode).getElementExpressions();
+            if (expressions != null) {
+                visitExpressions(expressions);
+            }
         }
+        pushExpressionType(literalNode);
         return false;
     }
 
     @Override
+    public boolean enterObjectNode(final ObjectNode objectNode) {
+        for(final PropertyNode propertyNode: objectNode.getElements()) {
+            // Avoid falsely adding property keys to the control flow graph
+            final Expression value = propertyNode.getValue();
+            if (value != null) {
+                visitExpression(value);
+            }
+        }
+        return pushExpressionType(objectNode);
+    }
+
+    @Override
+    public boolean enterPropertyNode(final PropertyNode propertyNode) {
+        // Property nodes are only accessible through object literals, and we handled that case above
+        throw new AssertionError();
+    }
+
+    @Override
     public boolean enterReturnNode(final ReturnNode returnNode) {
         if(!reachable) {
             return false;
@@ -684,9 +830,9 @@
         final Expression returnExpr = returnNode.getExpression();
         final Type returnExprType;
         if(returnExpr != null) {
-            returnExpr.accept(this);
-            returnExprType = getType(returnExpr);
+            returnExprType = visitExpressionOnEmptyStack(returnExpr).type;
         } else {
+            assertTypeStackIsEmpty();
             returnExprType = Type.UNDEFINED;
         }
         returnType = Type.widestReturnType(returnType, returnExprType);
@@ -695,6 +841,12 @@
     }
 
     @Override
+    public boolean enterRuntimeNode(final RuntimeNode runtimeNode) {
+        visitExpressions(runtimeNode.getArgs());
+        return pushExpressionType(runtimeNode);
+    }
+
+    @Override
     public boolean enterSplitReturn(final SplitReturn splitReturn) {
         doesNotContinueSequentially();
         return false;
@@ -706,8 +858,7 @@
             return false;
         }
 
-        final Expression expr = switchNode.getExpression();
-        expr.accept(this);
+        visitExpressionOnEmptyStack(switchNode.getExpression());
 
         final List<CaseNode> cases = switchNode.getCases();
         if(cases.isEmpty()) {
@@ -724,7 +875,7 @@
         for(final CaseNode caseNode: cases) {
             final Expression test = caseNode.getTest();
             if(!isInteger && test != null) {
-                test.accept(this);
+                visitExpressionOnEmptyStack(test);
                 if(!tagUsed) {
                     symbolIsUsed(switchNode.getTag(), LvarType.OBJECT);
                     tagUsed = true;
@@ -769,29 +920,42 @@
         final Expression trueExpr = ternaryNode.getTrueExpression();
         final Expression falseExpr = ternaryNode.getFalseExpression();
 
-        test.accept(this);
+        visitExpression(test);
 
         final Map<Symbol, LvarType> testExitLvarTypes = localVariableTypes;
+        final LvarType trueType;
         if(!isAlwaysFalse(test)) {
-            trueExpr.accept(this);
+            trueType = visitExpression(trueExpr);
+        } else {
+            trueType = null;
         }
         final Map<Symbol, LvarType> trueExitLvarTypes = localVariableTypes;
         localVariableTypes = testExitLvarTypes;
+        final LvarType falseType;
         if(!isAlwaysTrue(test)) {
-            falseExpr.accept(this);
+            falseType = visitExpression(falseExpr);
+        } else {
+            falseType = null;
         }
         final Map<Symbol, LvarType> falseExitLvarTypes = localVariableTypes;
         localVariableTypes = getUnionTypes(trueExitLvarTypes, falseExitLvarTypes);
         setConversion((JoinPredecessor)trueExpr, trueExitLvarTypes, localVariableTypes);
         setConversion((JoinPredecessor)falseExpr, falseExitLvarTypes, localVariableTypes);
+
+        typeStack.push(trueType != null ? falseType != null ? widestLvarType(trueType, falseType) : trueType : assertNotNull(falseType));
         return false;
     }
 
+    private static <T> T assertNotNull(final T t) {
+        assert t != null;
+        return t;
+    }
+
     private void enterTestFirstLoop(final LoopNode loopNode, final JoinPredecessorExpression modify,
             final Expression iteratorValues, final boolean iteratorValuesAreObject) {
         final JoinPredecessorExpression test = loopNode.getTest();
         if(isAlwaysFalse(test)) {
-            test.accept(this);
+            visitExpressionOnEmptyStack(test);
             return;
         }
 
@@ -804,7 +968,7 @@
             jumpToLabel(loopNode, repeatLabel, beforeLoopTypes);
             final Map<Symbol, LvarType> beforeRepeatTypes = localVariableTypes;
             if(test != null) {
-                test.accept(this);
+                visitExpressionOnEmptyStack(test);
             }
             if(!isAlwaysTrue(test)) {
                 jumpToLabel(test, breakLabel);
@@ -827,7 +991,7 @@
                 break;
             }
             if(modify != null) {
-                modify.accept(this);
+                visitExpressionOnEmptyStack(modify);
                 jumpToLabel(modify, repeatLabel);
                 joinOnLabel(repeatLabel);
             }
@@ -853,7 +1017,7 @@
             return false;
         }
 
-        throwNode.getExpression().accept(this);
+        visitExpressionOnEmptyStack(throwNode.getExpression());
         jumpToCatchBlock(throwNode);
         doesNotContinueSequentially();
         return false;
@@ -886,13 +1050,24 @@
         }
         doesNotContinueSequentially();
 
+        for (final Block inlinedFinally : tryNode.getInlinedFinallies()) {
+            final Block finallyBody = TryNode.getLabelledInlinedFinallyBlock(inlinedFinally);
+            joinOnLabel(finallyBody.getEntryLabel());
+            // NOTE: the jump to inlined finally can end up in dead code, so it is not necessarily reachable.
+            if (reachable) {
+                finallyBody.accept(this);
+                // All inlined finallies end with a jump or a return
+                assert !reachable;
+            }
+        }
+
         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);
+                visitExpression(condition);
             }
             final Map<Symbol, LvarType> afterConditionTypes = localVariableTypes;
             final Block catchBody = catchNode.getBody();
@@ -927,14 +1102,11 @@
     @Override
     public boolean enterUnaryNode(final UnaryNode unaryNode) {
         final Expression expr = unaryNode.getExpression();
-        expr.accept(this);
-
-        if(unaryNode.isSelfModifying()) {
-            if(expr instanceof IdentNode) {
-                final IdentNode ident = (IdentNode)expr;
-                onSelfAssignment(ident, unaryNode, getLocalVariableTypeIfBytecode(ident.getSymbol()));
-            }
+        final LvarType unaryType = toLvarType(unaryNode.setExpression(visitExpression(expr).typeExpression).getType());
+        if(unaryNode.isSelfModifying() && expr instanceof IdentNode) {
+            onSelfAssignment((IdentNode)expr, unaryType);
         }
+        typeStack.push(unaryType);
         return false;
     }
 
@@ -945,8 +1117,7 @@
         }
         final Expression init = varNode.getInit();
         if(init != null) {
-            init.accept(this);
-            onAssignment(varNode.getName(), init);
+            onAssignment(varNode.getName(), visitExpression(init));
         }
         return false;
     }
@@ -964,7 +1135,16 @@
         return false;
     }
 
-    private Map<Symbol, LvarType> getBreakTargetTypes(final BreakableNode target) {
+    @Override
+    public boolean enterWithNode(final WithNode withNode) {
+        if (reachable) {
+            visitExpression(withNode.getExpression());
+            withNode.getBody().accept(this);
+        }
+        return false;
+    };
+
+    private Map<Symbol, LvarType> getBreakTargetTypes(final LexicalContextNode 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();) {
@@ -1002,18 +1182,6 @@
     }
 
     /**
-     * Gets the type for a local variable if it is a bytecode local, otherwise null. Can be used in circumstances where
-     * the type is irrelevant if the symbol is not a bytecode local. Note that for bytecode locals, it delegates to
-     * {@link #getLocalVariableType(Symbol)}, so it will still assert that the type for such variable is already
-     * defined (that is, not null).
-     * @param symbol the symbol representing the variable.
-     * @return the current variable type, if it is a bytecode local, otherwise null.
-     */
-    private LvarType getLocalVariableTypeIfBytecode(final Symbol symbol) {
-        return symbol.isBytecodeLocal() ? getLocalVariableType(symbol) : null;
-    }
-
-    /**
      * Gets the type for a variable represented by a symbol, or null if the type is not know. This is the least strict
      * of all local variable type getters, and as such its use is discouraged except in initialization scenarios (where
      * a just-defined symbol might still be null).
@@ -1154,6 +1322,7 @@
      */
     private void leaveBreakable(final BreakableNode breakable) {
         joinOnLabel(breakable.getBreakLabel());
+        assertTypeStackIsEmpty();
     }
 
     @Override
@@ -1161,7 +1330,7 @@
         // 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()) {
+        final SimpleNodeVisitor applyChangesVisitor = new SimpleNodeVisitor() {
             private boolean inOuterFunction = true;
             private final Deque<JoinPredecessor> joinPredecessors = new ArrayDeque<>();
 
@@ -1193,8 +1362,6 @@
                     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:
@@ -1207,14 +1374,12 @@
                         }
                         // Specialize comparison of boolean with non-boolean
                         if (lhs.getType().isBoolean() != rhs.getType().isBoolean()) {
-                            newRuntimeNode = true;
-                            cmpWidest = Type.OBJECT;
-                            finalized = true;
+                            return new RuntimeNode(binaryNode);
                         }
                         // fallthrough
                     default:
-                        if (newRuntimeNode || cmpWidest.isObject()) {
-                            return new RuntimeNode(binaryNode).setIsFinal(finalized);
+                        if (lhs.getType().isObject() && rhs.getType().isObject()) {
+                            return new RuntimeNode(binaryNode);
                         }
                     }
                 } else if(binaryNode.isOptimisticUndecidedType()) {
@@ -1230,7 +1395,11 @@
                 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);
+                    final JoinPredecessor newNode = setLocalVariableConversion(original, (JoinPredecessor)node);
+                    if (newNode instanceof LexicalContextNode) {
+                        lc.replace((LexicalContextNode)node, (LexicalContextNode)newNode);
+                    }
+                    return (Node)newNode;
                 }
                 return node;
             }
@@ -1308,7 +1477,6 @@
         newFunction = newFunction.setReturnType(lc, returnType);
 
 
-        newFunction = newFunction.setState(lc, CompilationState.LOCAL_VARIABLE_TYPES_CALCULATED);
         newFunction = newFunction.setParameters(lc, newFunction.visitParameters(applyChangesVisitor));
         return newFunction;
     }
@@ -1329,10 +1497,6 @@
         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();
@@ -1400,13 +1564,12 @@
         jumpToCatchBlock(identNode);
     }
 
-    private void onSelfAssignment(final IdentNode identNode, final Expression assignment, final LvarType typeOnLoad) {
+    private void onSelfAssignment(final IdentNode identNode, final LvarType type) {
         final Symbol symbol = identNode.getSymbol();
         assert symbol != null : identNode.getName();
         if(!symbol.isBytecodeLocal()) {
             return;
         }
-        final LvarType type = toLvarType(getType(assignment, symbol, typeOnLoad.type));
         // Self-assignment never produce either a boolean or undefined
         assert type != null && type != LvarType.UNDEFINED && type != LvarType.BOOLEAN;
         setType(symbol, type);
@@ -1466,7 +1629,6 @@
      * @param symbol the symbol representing the variable
      * @param type the type
      */
-    @SuppressWarnings("unused")
     private void setType(final Symbol symbol, final LvarType type) {
         if(getLocalVariableTypeOrNull(symbol) == type) {
             return;
@@ -1486,77 +1648,4 @@
     private void symbolIsUsed(final Symbol symbol) {
         symbolIsUsed(symbol, getLocalVariableType(symbol));
     }
-
-    /**
-     * Gets the type of the expression, dependent on the current types of the local variables.
-     *
-     * @param expr the expression
-     * @return the current type of the expression dependent on the current types of the local variables.
-     */
-    private Type getType(final Expression expr) {
-        return expr.getType(getSymbolToType());
-    }
-
-    /**
-     * Returns a function object from symbols to their types, used by the expressions to evaluate their type.
-     * {@link BinaryNode} specifically uses identity of the function to cache type calculations. This method makes
-     * sure to return the same function object while the local variable types don't change, and create a new function
-     * object if the local variable types have been changed.
-     * @return a function object representing a mapping from symbols to their types.
-     */
-    private Function<Symbol, Type> getSymbolToType() {
-        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;
-        }
-    }
-
-    /**
-     * Gets the type of the expression, dependent on the current types of the local variables and a single overridden
-     * symbol type. Used by type calculation on compound operators to ensure the type of the LHS at the time it was
-     * loaded (which can potentially be different after RHS evaluation, e.g. "var x; x += x = 0;") is preserved for
-     * the calculation.
-     *
-     * @param expr the expression
-     * @param overriddenSymbol the overridden symbol
-     * @param overriddenType the overridden type
-     * @return the current type of the expression dependent on the current types of the local variables and the single
-     * potentially overridden type.
-     */
-    private Type getType(final Expression expr, final Symbol overriddenSymbol, final Type overriddenType) {
-        return expr.getType(getSymbolToType(overriddenSymbol, overriddenType));
-    }
-
-    private Function<Symbol, Type> getSymbolToType(final Symbol overriddenSymbol, final Type overriddenType) {
-        return getLocalVariableType(overriddenSymbol).type == overriddenType ? getSymbolToType() :
-            new SymbolToTypeOverride(overriddenSymbol, overriddenType);
-    }
-
-    private class SymbolToTypeOverride implements Function<Symbol, Type> {
-        private final Function<Symbol, Type> originalSymbolToType = getSymbolToType();
-        private final Symbol overriddenSymbol;
-        private final Type overriddenType;
-
-        SymbolToTypeOverride(final Symbol overriddenSymbol, final Type overriddenType) {
-            this.overriddenSymbol = overriddenSymbol;
-            this.overriddenType = overriddenType;
-        }
-
-        @Override
-        public Type apply(final Symbol symbol) {
-            return symbol == overriddenSymbol ? overriddenType : originalSymbolToType.apply(symbol);
-        }
-    }
 }
diff --git a/src/jdk/nashorn/internal/codegen/Lower.java b/src/jdk/nashorn/internal/codegen/Lower.java
index a30e79a..1f0e5ae 100644
--- a/src/jdk/nashorn/internal/codegen/Lower.java
+++ b/src/jdk/nashorn/internal/codegen/Lower.java
@@ -51,14 +51,15 @@
 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.JumpStatement;
+import jdk.nashorn.internal.ir.JumpToInlinedFinally;
 import jdk.nashorn.internal.ir.LabelNode;
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
+import jdk.nashorn.internal.ir.LiteralNode.PrimitiveLiteralNode;
 import jdk.nashorn.internal.ir.LoopNode;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.ReturnNode;
@@ -72,7 +73,7 @@
 import jdk.nashorn.internal.ir.WhileNode;
 import jdk.nashorn.internal.ir.WithNode;
 import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.parser.Token;
 import jdk.nashorn.internal.parser.TokenType;
 import jdk.nashorn.internal.runtime.Context;
@@ -115,17 +116,11 @@
                 for (final Statement statement : statements) {
                     if (!terminated) {
                         newStatements.add(statement);
-                        if (statement.isTerminal() || statement instanceof BreakNode || statement instanceof ContinueNode) { //TODO hasGoto? But some Loops are hasGoto too - why?
+                        if (statement.isTerminal() || statement instanceof JumpStatement) { //TODO hasGoto? But some Loops are hasGoto too - why?
                             terminated = true;
                         }
                     } else {
-                        statement.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
-                            @Override
-                            public boolean enterVarNode(final VarNode varNode) {
-                                newStatements.add(varNode.setInit(null));
-                                return false;
-                            }
-                        });
+                        FoldConstants.extractVarNodesFromDeadCode(statement, newStatements);
                     }
                 }
                 return newStatements;
@@ -183,6 +178,12 @@
     }
 
     @Override
+    public boolean enterJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+        addStatement(jumpToInlinedFinally);
+        return false;
+    }
+
+    @Override
     public boolean enterEmptyNode(final EmptyNode emptyNode) {
         return false;
     }
@@ -192,7 +193,7 @@
         final String name = getConstantPropertyName(indexNode.getIndex());
         if (name != null) {
             // If index node is a constant property name convert index node to access node.
-            assert Token.descType(indexNode.getToken()) == TokenType.LBRACKET;
+            assert indexNode.isIndex();
             return new AccessNode(indexNode.getToken(), indexNode.getFinish(), indexNode.getBase(), name);
         }
         return super.leaveIndexNode(indexNode);
@@ -258,7 +259,7 @@
     @Override
     public Node leaveFunctionNode(final FunctionNode functionNode) {
         log.info("END FunctionNode: ", functionNode.getName());
-        return functionNode.setState(lc, CompilationState.LOWERED);
+        return functionNode;
     }
 
     @Override
@@ -318,8 +319,9 @@
         return addStatement(throwNode); //ThrowNodes are always terminal, marked as such in constructor
     }
 
-    private static Node ensureUniqueNamesIn(final Node node) {
-        return node.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+    @SuppressWarnings("unchecked")
+    private static <T extends Node> T ensureUniqueNamesIn(final T node) {
+        return (T)node.accept(new SimpleNodeVisitor() {
             @Override
             public Node leaveFunctionNode(final FunctionNode functionNode) {
                 final String name = functionNode.getName();
@@ -333,15 +335,15 @@
         });
     }
 
-    private static List<Statement> copyFinally(final Block finallyBody) {
+    private static Block createFinallyBlock(final Block finallyBody) {
         final List<Statement> newStatements = new ArrayList<>();
         for (final Statement statement : finallyBody.getStatements()) {
-            newStatements.add((Statement)ensureUniqueNamesIn(statement));
+            newStatements.add(statement);
             if (statement.hasTerminalFlags()) {
-                return newStatements;
+                break;
             }
         }
-        return newStatements;
+        return finallyBody.setStatements(null, newStatements);
     }
 
     private Block catchAllBlock(final TryNode tryNode) {
@@ -367,28 +369,24 @@
         return new IdentNode(functionNode.getToken(), functionNode.getFinish(), cc.symbolName());
     }
 
-    private static boolean isTerminal(final List<Statement> statements) {
-        return !statements.isEmpty() && statements.get(statements.size() - 1).hasTerminalFlags();
+    private static boolean isTerminalFinally(final Block finallyBlock) {
+        return finallyBlock.getLastStatement().hasTerminalFlags();
     }
 
     /**
      * Splice finally code into all endpoints of a trynode
      * @param tryNode the try node
-     * @param rethrows list of rethrowing throw nodes from synthetic catch blocks
+     * @param rethrow the rethrowing throw nodes from the synthetic catch block
      * @param finallyBody the code in the original finally block
      * @return new try node after splicing finally code (same if nop)
      */
-    private Node spliceFinally(final TryNode tryNode, final List<ThrowNode> rethrows, final Block finallyBody) {
+    private TryNode spliceFinally(final TryNode tryNode, final ThrowNode rethrow, final Block finallyBody) {
         assert tryNode.getFinallyBody() == null;
 
-        final TryNode newTryNode = (TryNode)tryNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
-            final List<Node> insideTry = new ArrayList<>();
-
-            @Override
-            public boolean enterDefault(final Node node) {
-                insideTry.add(node);
-                return true;
-            }
+        final Block finallyBlock = createFinallyBlock(finallyBody);
+        final ArrayList<Block> inlinedFinallies = new ArrayList<>();
+        final FunctionNode fn = lc.getCurrentFunction();
+        final TryNode newTryNode = (TryNode)tryNode.accept(new SimpleNodeVisitor() {
 
             @Override
             public boolean enterFunctionNode(final FunctionNode functionNode) {
@@ -398,12 +396,8 @@
 
             @Override
             public Node leaveThrowNode(final ThrowNode throwNode) {
-                if (rethrows.contains(throwNode)) {
-                    final List<Statement> newStatements = copyFinally(finallyBody);
-                    if (!isTerminal(newStatements)) {
-                        newStatements.add(throwNode);
-                    }
-                    return BlockStatement.createReplacement(throwNode, newStatements);
+                if (rethrow == throwNode) {
+                    return new BlockStatement(prependFinally(finallyBlock, throwNode));
                 }
                 return throwNode;
             }
@@ -419,62 +413,98 @@
             }
 
             private Node leaveJumpStatement(final JumpStatement jump) {
-                return copy(jump, (Node)jump.getTarget(Lower.this.lc));
+                // NOTE: leaveJumpToInlinedFinally deliberately does not delegate to this method, only break and
+                // continue are edited. JTIF nodes should not be changed, rather the surroundings of
+                // break/continue/return that were moved into the inlined finally block itself will be changed.
+
+                // If this visitor's lc doesn't find the target of the jump, it means it's external to the try block.
+                if (jump.getTarget(lc) == null) {
+                    return createJumpToInlinedFinally(fn, inlinedFinallies, prependFinally(finallyBlock, jump));
+                }
+                return jump;
             }
 
             @Override
             public Node leaveReturnNode(final ReturnNode returnNode) {
-                final Expression expr  = returnNode.getExpression();
-                final List<Statement> newStatements = new ArrayList<>();
-
-                final Expression resultNode;
-                if (expr != null) {
-                    //we need to evaluate the result of the return in case it is complex while
-                    //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)));
-                } else {
-                    resultNode = null;
-                }
-
-                newStatements.addAll(copyFinally(finallyBody));
-                if (!isTerminal(newStatements)) {
-                    newStatements.add(expr == null ? returnNode : returnNode.setExpression(resultNode));
-                }
-
-                return BlockStatement.createReplacement(returnNode, lc.getCurrentBlock().getFinish(), newStatements);
-            }
-
-            private Node copy(final Statement endpoint, final Node targetNode) {
-                if (!insideTry.contains(targetNode)) {
-                    final List<Statement> newStatements = copyFinally(finallyBody);
-                    if (!isTerminal(newStatements)) {
-                        newStatements.add(endpoint);
+                final Expression expr = returnNode.getExpression();
+                if (isTerminalFinally(finallyBlock)) {
+                    if (expr == null) {
+                        // Terminal finally; no return expression.
+                        return createJumpToInlinedFinally(fn, inlinedFinallies, ensureUniqueNamesIn(finallyBlock));
                     }
-                    return BlockStatement.createReplacement(endpoint, tryNode.getFinish(), newStatements);
+                    // Terminal finally; has a return expression.
+                    final List<Statement> newStatements = new ArrayList<>(2);
+                    final int retLineNumber = returnNode.getLineNumber();
+                    final long retToken = returnNode.getToken();
+                    // Expression is evaluated for side effects.
+                    newStatements.add(new ExpressionStatement(retLineNumber, retToken, returnNode.getFinish(), expr));
+                    newStatements.add(createJumpToInlinedFinally(fn, inlinedFinallies, ensureUniqueNamesIn(finallyBlock)));
+                    return new BlockStatement(retLineNumber, new Block(retToken, finallyBlock.getFinish(), newStatements));
+                } else if (expr == null || expr instanceof PrimitiveLiteralNode<?> || (expr instanceof IdentNode && RETURN.symbolName().equals(((IdentNode)expr).getName()))) {
+                    // Nonterminal finally; no return expression, or returns a primitive literal, or returns :return.
+                    // Just move the return expression into the finally block.
+                    return createJumpToInlinedFinally(fn, inlinedFinallies, prependFinally(finallyBlock, returnNode));
+                } else {
+                    // We need to evaluate the result of the return in case it is complex while still in the try block,
+                    // store it in :return, and return it afterwards.
+                    final List<Statement> newStatements = new ArrayList<>();
+                    final int retLineNumber = returnNode.getLineNumber();
+                    final long retToken = returnNode.getToken();
+                    final int retFinish = returnNode.getFinish();
+                    final Expression resultNode = new IdentNode(expr.getToken(), expr.getFinish(), RETURN.symbolName());
+                    // ":return = <expr>;"
+                    newStatements.add(new ExpressionStatement(retLineNumber, retToken, retFinish, new BinaryNode(Token.recast(returnNode.getToken(), TokenType.ASSIGN), resultNode, expr)));
+                    // inline finally and end it with "return :return;"
+                    newStatements.add(createJumpToInlinedFinally(fn, inlinedFinallies, prependFinally(finallyBlock, returnNode.setExpression(resultNode))));
+                    return new BlockStatement(retLineNumber, new Block(retToken, retFinish, newStatements));
                 }
-                return endpoint;
             }
         });
-
-        addStatement(newTryNode);
-        for (final Node statement : finallyBody.getStatements()) {
-            addStatement((Statement)statement);
-        }
+        addStatement(inlinedFinallies.isEmpty() ? newTryNode : newTryNode.setInlinedFinallies(lc, inlinedFinallies));
+        // TODO: if finallyStatement is terminal, we could just have sites of inlined finallies jump here.
+        addStatement(new BlockStatement(finallyBlock));
 
         return newTryNode;
     }
 
+    private static JumpToInlinedFinally createJumpToInlinedFinally(final FunctionNode fn, final List<Block> inlinedFinallies, final Block finallyBlock) {
+        final String labelName = fn.uniqueName(":finally");
+        final long token = finallyBlock.getToken();
+        final int finish = finallyBlock.getFinish();
+        inlinedFinallies.add(new Block(token, finish, new LabelNode(finallyBlock.getFirstStatementLineNumber(),
+                token, finish, labelName, finallyBlock)));
+        return new JumpToInlinedFinally(labelName);
+    }
+
+    private static Block prependFinally(final Block finallyBlock, final Statement statement) {
+        final Block inlinedFinally = ensureUniqueNamesIn(finallyBlock);
+        if (isTerminalFinally(finallyBlock)) {
+            return inlinedFinally;
+        }
+        final List<Statement> stmts = inlinedFinally.getStatements();
+        final List<Statement> newStmts = new ArrayList<>(stmts.size() + 1);
+        newStmts.addAll(stmts);
+        newStmts.add(statement);
+        return new Block(inlinedFinally.getToken(), statement.getFinish(), newStmts);
+    }
+
     @Override
     public Node leaveTryNode(final TryNode tryNode) {
         final Block finallyBody = tryNode.getFinallyBody();
+        TryNode newTryNode = tryNode.setFinallyBody(lc, null);
 
-        if (finallyBody == null) {
-            return addStatement(ensureUnconditionalCatch(tryNode));
+        // No finally or empty finally
+        if (finallyBody == null || finallyBody.getStatementCount() == 0) {
+            final List<CatchNode> catches = newTryNode.getCatches();
+            if (catches == null || catches.isEmpty()) {
+                // A completely degenerate try block: empty finally, no catches. Replace it with try body.
+                return addStatement(new BlockStatement(tryNode.getBody()));
+            }
+            return addStatement(ensureUnconditionalCatch(newTryNode));
         }
 
         /*
-         * create a new trynode
+         * create a new try node
          *    if we have catches:
          *
          *    try            try
@@ -485,7 +515,7 @@
          *                   catchall
          *                        rethrow
          *
-         *   otheriwse
+         *   otherwise
          *
          *   try              try
          *      x               x
@@ -496,12 +526,10 @@
          *   now splice in finally code wherever needed
          *
          */
-        TryNode newTryNode;
-
         final Block catchAll = catchAllBlock(tryNode);
 
-        final List<ThrowNode> rethrows = new ArrayList<>();
-        catchAll.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        final List<ThrowNode> rethrows = new ArrayList<>(1);
+        catchAll.accept(new SimpleNodeVisitor() {
             @Override
             public boolean enterThrowNode(final ThrowNode throwNode) {
                 rethrows.add(throwNode);
@@ -510,20 +538,18 @@
         });
         assert rethrows.size() == 1;
 
-        if (tryNode.getCatchBlocks().isEmpty()) {
-            newTryNode = tryNode.setFinallyBody(null);
-        } else {
-            final Block outerBody = new Block(tryNode.getToken(), tryNode.getFinish(), ensureUnconditionalCatch(tryNode.setFinallyBody(null)));
-            newTryNode = tryNode.setBody(outerBody).setCatchBlocks(null);
+        if (!tryNode.getCatchBlocks().isEmpty()) {
+            final Block outerBody = new Block(newTryNode.getToken(), newTryNode.getFinish(), ensureUnconditionalCatch(newTryNode));
+            newTryNode = newTryNode.setBody(lc, outerBody).setCatchBlocks(lc, null);
         }
 
-        newTryNode = newTryNode.setCatchBlocks(Arrays.asList(catchAll)).setFinallyBody(null);
+        newTryNode = newTryNode.setCatchBlocks(lc, Arrays.asList(catchAll));
 
         /*
          * Now that the transform is done, we have to go into the try and splice
          * the finally block in front of any statement that is outside the try
          */
-        return spliceFinally(newTryNode, rethrows, finallyBody);
+        return (TryNode)lc.replace(tryNode, spliceFinally(newTryNode, rethrows.get(0), finallyBody));
     }
 
     private TryNode ensureUnconditionalCatch(final TryNode tryNode) {
@@ -535,7 +561,7 @@
         final List<Block> newCatchBlocks = new ArrayList<>(tryNode.getCatchBlocks());
 
         newCatchBlocks.add(catchAllBlock(tryNode));
-        return tryNode.setCatchBlocks(newCatchBlocks);
+        return tryNode.setCatchBlocks(lc, newCatchBlocks);
     }
 
     @Override
@@ -648,7 +674,7 @@
     private static boolean controlFlowEscapes(final LexicalContext lex, final Block loopBody) {
         final List<Node> escapes = new ArrayList<>();
 
-        loopBody.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        loopBody.accept(new SimpleNodeVisitor() {
             @Override
             public Node leaveBreakNode(final BreakNode node) {
                 escapes.add(node);
diff --git a/src/jdk/nashorn/internal/codegen/MapCreator.java b/src/jdk/nashorn/internal/codegen/MapCreator.java
index 1bec86f..be99db9 100644
--- a/src/jdk/nashorn/internal/codegen/MapCreator.java
+++ b/src/jdk/nashorn/internal/codegen/MapCreator.java
@@ -68,17 +68,17 @@
      * @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, final boolean evalCode) {
+    PropertyMap makeFieldMap(final boolean hasArguments, final boolean dualFields, final int fieldCount, final int fieldMaximum, final boolean evalCode) {
         final List<Property> properties = new ArrayList<>();
         assert tuples != null;
 
         for (final MapTuple<T> tuple : tuples) {
             final String   key         = tuple.key;
             final Symbol   symbol      = tuple.symbol;
-            final Class<?> initialType = tuple.getValueType();
+            final Class<?> initialType = dualFields ? tuple.getValueType() : Object.class;
 
             if (symbol != null && !isValidArrayIndex(getArrayIndex(key))) {
-                final int      flags    = getPropertyFlags(symbol, hasArguments, evalCode);
+                final int      flags    = getPropertyFlags(symbol, hasArguments, evalCode, dualFields);
                 final Property property = new AccessorProperty(
                         key,
                         flags,
@@ -92,7 +92,7 @@
         return PropertyMap.newMap(properties, structure.getName(), fieldCount, fieldMaximum, 0);
     }
 
-    PropertyMap makeSpillMap(final boolean hasArguments) {
+    PropertyMap makeSpillMap(final boolean hasArguments, final boolean dualFields) {
         final List<Property> properties = new ArrayList<>();
         int spillIndex = 0;
         assert tuples != null;
@@ -100,15 +100,16 @@
         for (final MapTuple<T> tuple : tuples) {
             final String key    = tuple.key;
             final Symbol symbol = tuple.symbol;
+            final Class<?> initialType = dualFields ? tuple.getValueType() : Object.class;
 
-            //TODO initial type is object here no matter what. Is that right?
             if (symbol != null && !isValidArrayIndex(getArrayIndex(key))) {
-                final int flags = getPropertyFlags(symbol, hasArguments, false);
+                final int flags = getPropertyFlags(symbol, hasArguments, false, dualFields);
                 properties.add(
                         new SpillProperty(
                                 key,
                                 flags,
-                                spillIndex++));
+                                spillIndex++,
+                                initialType));
             }
         }
 
@@ -123,7 +124,7 @@
      *
      * @return flags to use for fields
      */
-    static int getPropertyFlags(final Symbol symbol, final boolean hasArguments, final boolean evalCode) {
+    static int getPropertyFlags(final Symbol symbol, final boolean hasArguments, final boolean evalCode, final boolean dualFields) {
         int flags = 0;
 
         if (symbol.isParam()) {
@@ -161,6 +162,10 @@
             flags |= Property.NEEDS_DECLARATION;
         }
 
+        if (dualFields) {
+            flags |= Property.DUAL_FIELDS;
+        }
+
         return flags;
     }
 }
diff --git a/src/jdk/nashorn/internal/codegen/MapTuple.java b/src/jdk/nashorn/internal/codegen/MapTuple.java
index 024c3d6..44cdc8b 100644
--- a/src/jdk/nashorn/internal/codegen/MapTuple.java
+++ b/src/jdk/nashorn/internal/codegen/MapTuple.java
@@ -25,8 +25,6 @@
 
 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;
 
@@ -52,11 +50,11 @@
     }
 
     public Class<?> getValueType() {
-        return OBJECT_FIELDS_ONLY ? Object.class : null; //until proven otherwise we are undefined, see NASHORN-592 int.class;
+        return null; //until proven otherwise we are undefined, see NASHORN-592 int.class;
     }
 
     boolean isPrimitive() {
-        return !OBJECT_FIELDS_ONLY && getValueType().isPrimitive() && getValueType() != boolean.class;
+        return getValueType() != null && getValueType().isPrimitive() && getValueType() != boolean.class;
     }
 
     @Override
diff --git a/src/jdk/nashorn/internal/codegen/MethodEmitter.java b/src/jdk/nashorn/internal/codegen/MethodEmitter.java
index 362a736..f5bc303 100644
--- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java
+++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java
@@ -94,7 +94,6 @@
 import jdk.nashorn.internal.ir.JoinPredecessor;
 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;
@@ -125,7 +124,7 @@
  * all generated bytecode and labels to stderr, for easier debugging,
  * including bytecode stack contents
  */
-public class MethodEmitter implements Emitter {
+public class MethodEmitter {
     /** The ASM MethodVisitor we are plugged into */
     private final MethodVisitor method;
 
@@ -138,9 +137,6 @@
     /** Current type stack for current evaluation */
     private Label.Stack stack;
 
-    /** Check whether this emitter ever has a function return point */
-    private boolean hasReturn;
-
     private boolean preventUndefinedLoad;
 
     /**
@@ -175,9 +171,6 @@
     /** Bootstrap for normal indy:s */
     private static final Handle LINKERBOOTSTRAP  = new Handle(H_INVOKESTATIC, Bootstrap.BOOTSTRAP.className(), Bootstrap.BOOTSTRAP.name(), Bootstrap.BOOTSTRAP.descriptor());
 
-    /** 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());
 
@@ -212,9 +205,7 @@
 
     /**
      * Begin a method
-     * @see Emitter
      */
-    @Override
     public void begin() {
         classEmitter.beginMethod(this);
         newStack();
@@ -223,9 +214,7 @@
 
     /**
      * End a method
-     * @see Emitter
      */
-    @Override
     public void end() {
         method.visitMaxs(0, 0);
         method.visitEnd();
@@ -269,8 +258,7 @@
      */
     private Type popType(final Type expected) {
         final Type type = popType();
-        assert type.isObject() && expected.isObject() ||
-            type.isEquivalentTo(expected) : type + " is not compatible with " + expected;
+        assert type.isEquivalentTo(expected) : type + " is not compatible with " + expected;
         return type;
     }
 
@@ -1170,7 +1158,7 @@
     /**
      * 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
+     * do the bookkeeping 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.
@@ -1592,7 +1580,7 @@
     /**
      * Abstraction for performing a conditional jump of any type
      *
-     * @see MethodEmitter.Condition
+     * @see Condition
      *
      * @param cond      the condition to test
      * @param trueLabel the destination label is condition is true
@@ -1620,15 +1608,6 @@
         }
     }
 
-    MethodEmitter registerReturn() {
-        setHasReturn();
-        return this;
-    }
-
-    void setHasReturn() {
-        this.hasReturn = true;
-    }
-
     /**
      * Perform a non void return, popping the type from the stack
      *
@@ -2153,10 +2132,25 @@
      * @return the method emitter
      */
     MethodEmitter dynamicNew(final int argCount, final int flags) {
+        return dynamicNew(argCount, flags, null);
+    }
+
+    /**
+     * Generate a dynamic new
+     *
+     * @param argCount  number of arguments
+     * @param flags     callsite flags
+     * @param msg        additional message to be used when reporting error
+     *
+     * @return the method emitter
+     */
+    MethodEmitter dynamicNew(final int argCount, final int flags, final String msg) {
         assert !isOptimistic(flags);
         debug("dynamic_new", "argcount=", argCount);
         final String signature = getDynamicSignature(Type.OBJECT, argCount);
-        method.visitInvokeDynamicInsn("dyn:new", signature, LINKERBOOTSTRAP, flags);
+        method.visitInvokeDynamicInsn(
+                msg != null && msg.length() < LARGE_STRING_THRESHOLD? "dyn:new:" + NameCodec.encode(msg) : "dyn:new",
+                signature, LINKERBOOTSTRAP, flags);
         pushType(Type.OBJECT); //TODO fix result type
         return this;
     }
@@ -2171,10 +2165,26 @@
      * @return the method emitter
      */
     MethodEmitter dynamicCall(final Type returnType, final int argCount, final int flags) {
+        return dynamicCall(returnType, argCount, flags, null);
+    }
+
+    /**
+     * Generate a dynamic call
+     *
+     * @param returnType return type
+     * @param argCount   number of arguments
+     * @param flags      callsite flags
+     * @param msg        additional message to be used when reporting error
+     *
+     * @return the method emitter
+     */
+    MethodEmitter dynamicCall(final Type returnType, final int argCount, final int flags, final String msg) {
         debug("dynamic_call", "args=", argCount, "returnType=", returnType);
         final String signature = getDynamicSignature(returnType, argCount); // +1 because the function itself is the 1st parameter for dynamic calls (what you call - call target)
         debug("   signature", signature);
-        method.visitInvokeDynamicInsn("dyn:call", signature, LINKERBOOTSTRAP, flags);
+        method.visitInvokeDynamicInsn(
+                msg != null && msg.length() < LARGE_STRING_THRESHOLD? "dyn:call:" + NameCodec.encode(msg) : "dyn:call",
+                signature, LINKERBOOTSTRAP, flags);
         pushType(returnType);
 
         return this;
@@ -2189,25 +2199,6 @@
     }
 
     /**
-     * Generate a dynamic call for a runtime node
-     *
-     * @param name       tag for the invoke dynamic for this runtime node
-     * @param returnType return type
-     * @param request    RuntimeNode request
-     *
-     * @return the method emitter
-     */
-    MethodEmitter dynamicRuntimeCall(final String name, final Type returnType, final RuntimeNode.Request request) {
-        debug("dynamic_runtime_call", name, "args=", request.getArity(), "returnType=", returnType);
-        final String signature = getDynamicSignature(returnType, request.getArity());
-        debug("   signature", signature);
-        method.visitInvokeDynamicInsn(name, signature, RUNTIMEBOOTSTRAP);
-        pushType(returnType);
-
-        return this;
-    }
-
-    /**
      * Generate dynamic getter. Pop scope from stack. Push result
      *
      * @param valueType type of the value to set
@@ -2218,6 +2209,10 @@
      * @return the method emitter
      */
     MethodEmitter dynamicGet(final Type valueType, final String name, final int flags, final boolean isMethod, final boolean isIndex) {
+        if (name.length() > LARGE_STRING_THRESHOLD) { // use getIndex for extremely long names
+            return load(name).dynamicGetIndex(valueType, flags, isMethod);
+        }
+
         debug("dynamic_get", name, valueType, getProgramPoint(flags));
 
         Type type = valueType;
@@ -2243,8 +2238,13 @@
      * @param isIndex is this an index operation?
      */
     void dynamicSet(final String name, final int flags, final boolean isIndex) {
-         assert !isOptimistic(flags);
-         debug("dynamic_set", name, peekType());
+        if (name.length() > LARGE_STRING_THRESHOLD) { // use setIndex for extremely long names
+            load(name).swap().dynamicSetIndex(flags);
+            return;
+        }
+
+        assert !isOptimistic(flags);
+        debug("dynamic_set", name, peekType());
 
         Type type = peekType();
         if (type.isObject() || type.isBoolean()) { //promote strings to objects etc
@@ -2739,10 +2739,6 @@
         this.functionNode = functionNode;
     }
 
-    boolean hasReturn() {
-        return hasReturn;
-    }
-
     /**
      * 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
diff --git a/src/jdk/nashorn/internal/codegen/Namespace.java b/src/jdk/nashorn/internal/codegen/Namespace.java
index 5c5115a..17304a9 100644
--- a/src/jdk/nashorn/internal/codegen/Namespace.java
+++ b/src/jdk/nashorn/internal/codegen/Namespace.java
@@ -25,6 +25,8 @@
 
 package jdk.nashorn.internal.codegen;
 
+import static jdk.nashorn.internal.codegen.MethodEmitter.LARGE_STRING_THRESHOLD;
+
 import java.util.HashMap;
 
 /**
@@ -66,27 +68,28 @@
     }
 
     /**
-     * Create a uniqueName name in the namespace in the form base$n where n varies
-     * .
-     * @param base Base of name.  Base will be returned if uniqueName.
+     * Create a uniqueName name in the namespace in the form base$n where n varies.
+     * Also truncates very long names that would otherwise break ASM.
      *
+     * @param base Base of name.  Base will be returned if uniqueName.
      * @return Generated uniqueName name.
      */
     public String uniqueName(final String base) {
+        final String truncatedBase = base.length() > LARGE_STRING_THRESHOLD ? base.substring(0, LARGE_STRING_THRESHOLD) : base;
         for (Namespace namespace = this; namespace != null; namespace = namespace.getParent()) {
             final HashMap<String, Integer> namespaceDirectory = namespace.directory;
-            final Integer                  counter            = namespaceDirectory.get(base);
+            final Integer                  counter            = namespaceDirectory.get(truncatedBase);
 
             if (counter != null) {
                 final int count = counter + 1;
-                namespaceDirectory.put(base, count);
-                return base + '-' + count;
+                namespaceDirectory.put(truncatedBase, count);
+                return truncatedBase + '-' + count;
             }
         }
 
-        directory.put(base, 0);
+        directory.put(truncatedBase, 0);
 
-        return base;
+        return truncatedBase;
     }
 
     @Override
diff --git a/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java b/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java
index a5a5cf6..f753685 100644
--- a/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java
+++ b/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java
@@ -31,7 +31,8 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.INIT_MAP;
 import static jdk.nashorn.internal.codegen.CompilerConstants.INIT_SCOPE;
 import static jdk.nashorn.internal.codegen.CompilerConstants.JAVA_THIS;
-import static jdk.nashorn.internal.codegen.CompilerConstants.JS_OBJECT_PREFIX;
+import static jdk.nashorn.internal.codegen.CompilerConstants.JS_OBJECT_DUAL_FIELD_PREFIX;
+import static jdk.nashorn.internal.codegen.CompilerConstants.JS_OBJECT_SINGLE_FIELD_PREFIX;
 import static jdk.nashorn.internal.codegen.CompilerConstants.className;
 import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup;
 import static jdk.nashorn.internal.lookup.Lookup.MH;
@@ -56,6 +57,7 @@
 import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.runtime.AccessorProperty;
+import jdk.nashorn.internal.runtime.AllocationStrategy;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.FunctionScope;
 import jdk.nashorn.internal.runtime.JSType;
@@ -67,7 +69,6 @@
 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.
@@ -98,18 +99,10 @@
      */
     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.
-     *
-     * This is engineered to plug into the TaggedArray implementation, when it's done.
-     */
-    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<>();
+    /** Field types for object-only fields */
+    private static final Type[] FIELD_TYPES_OBJECT = new Type[] { Type.OBJECT };
+    /** Field types for dual primitive/object fields */
+    private static final Type[] FIELD_TYPES_DUAL   = new Type[] { Type.LONG, Type.OBJECT };
 
     /** What type is the primitive type in dual representation */
     public static final Type PRIMITIVE_FIELD_TYPE = Type.LONG;
@@ -117,33 +110,27 @@
     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
-     * LONG + OBJECT or just OBJECT for classic mode.
-     */
-    static {
-        if (!OBJECT_FIELDS_ONLY) {
-            FIELD_TYPES.add(PRIMITIVE_FIELD_TYPE);
-        }
-        FIELD_TYPES.add(Type.OBJECT);
-    }
     private static boolean initialized = false;
 
     /** The context */
     private final Context context;
 
+    private final boolean dualFields;
+
     /**
      * Constructor
      *
      * @param context a context
+     * @param dualFields whether to use dual fields representation
      */
-    public ObjectClassGenerator(final Context context) {
+    public ObjectClassGenerator(final Context context, final boolean dualFields) {
         this.context = context;
+        this.dualFields = dualFields;
         assert context != null;
         this.log = initLogger(context);
         if (!initialized) {
             initialized = true;
-            if (OBJECT_FIELDS_ONLY) {
+            if (!dualFields) {
                 log.warning("Running with object fields only - this is a deprecated configuration.");
             }
         }
@@ -175,16 +162,30 @@
         throw new AssertionError("cannot pack" + n);
     }
 
+    private static String getPrefixName(final boolean dualFields) {
+        return dualFields ? JS_OBJECT_DUAL_FIELD_PREFIX.symbolName() : JS_OBJECT_SINGLE_FIELD_PREFIX.symbolName();
+    }
+
+    private static String getPrefixName(final String className) {
+        if (className.startsWith(JS_OBJECT_DUAL_FIELD_PREFIX.symbolName())) {
+            return getPrefixName(true);
+        } else if (className.startsWith(JS_OBJECT_SINGLE_FIELD_PREFIX.symbolName())) {
+            return getPrefixName(false);
+        }
+        throw new AssertionError("Not a structure class: " + className);
+    }
+
     /**
      * Returns the class name for JavaScript objects with fieldCount fields.
      *
      * @param fieldCount Number of fields to allocate.
-     *
+     * @param dualFields whether to use dual fields representation
      * @return The class name.
      */
-    public static String getClassName(final int fieldCount) {
-        return fieldCount != 0 ? SCRIPTS_PACKAGE + '/' + JS_OBJECT_PREFIX.symbolName() + fieldCount :
-                                 SCRIPTS_PACKAGE + '/' + JS_OBJECT_PREFIX.symbolName();
+    public static String getClassName(final int fieldCount, final boolean dualFields) {
+        final String prefix = getPrefixName(dualFields);
+        return fieldCount != 0 ? SCRIPTS_PACKAGE + '/' + prefix + fieldCount :
+                                 SCRIPTS_PACKAGE + '/' + prefix;
     }
 
     /**
@@ -193,22 +194,23 @@
      *
      * @param fieldCount Number of fields to allocate.
      * @param paramCount Number of parameters to allocate
-     *
+     * @param dualFields whether to use dual fields representation
      * @return The class name.
      */
-    public static String getClassName(final int fieldCount, final int paramCount) {
-        return SCRIPTS_PACKAGE + '/' + JS_OBJECT_PREFIX.symbolName() + fieldCount + SCOPE_MARKER + paramCount;
+    public static String getClassName(final int fieldCount, final int paramCount, final boolean dualFields) {
+        return SCRIPTS_PACKAGE + '/' + getPrefixName(dualFields) + fieldCount + SCOPE_MARKER + paramCount;
     }
 
     /**
      * Returns the number of fields in the JavaScript scope class. Its name had to be generated using either
-     * {@link #getClassName(int)} or {@link #getClassName(int, int)}.
+     * {@link #getClassName(int, boolean)} or {@link #getClassName(int, int, boolean)}.
      * @param clazz the JavaScript scope class.
      * @return the number of fields in the scope class.
      */
     public static int getFieldCount(final Class<?> clazz) {
         final String name = clazz.getSimpleName();
-        final String prefix = JS_OBJECT_PREFIX.symbolName();
+        final String prefix = getPrefixName(name);
+
         if (prefix.equals(name)) {
             return 0;
         }
@@ -237,8 +239,8 @@
      * @param className  name of class
      * @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) {
+    private void initializeToUndefined(final MethodEmitter init, final String className, final List<String> fieldNames) {
+        if (dualFields) {
             // 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;
@@ -291,7 +293,7 @@
      * @return Byte codes for generated class.
      */
     public byte[] generate(final int fieldCount) {
-        final String       className    = getClassName(fieldCount);
+        final String       className    = getClassName(fieldCount, dualFields);
         final String       superName    = className(ScriptObject.class);
         final ClassEmitter classEmitter = newClassEmitter(className, superName);
 
@@ -321,7 +323,7 @@
      * @return Byte codes for generated class.
      */
     public byte[] generate(final int fieldCount, final int paramCount) {
-        final String       className    = getClassName(fieldCount, paramCount);
+        final String       className    = getClassName(fieldCount, paramCount, dualFields);
         final String       superName    = className(FunctionScope.class);
         final ClassEmitter classEmitter = newClassEmitter(className, superName);
         final List<String> initFields   = addFields(classEmitter, fieldCount);
@@ -352,11 +354,11 @@
      *
      * @return List fields that need to be initialized.
      */
-    private static List<String> addFields(final ClassEmitter classEmitter, final int fieldCount) {
+    private List<String> addFields(final ClassEmitter classEmitter, final int fieldCount) {
         final List<String> initFields = new LinkedList<>();
-
+        final Type[] fieldTypes = dualFields ? FIELD_TYPES_DUAL : FIELD_TYPES_OBJECT;
         for (int i = 0; i < fieldCount; i++) {
-            for (final Type type : FIELD_TYPES) {
+            for (final Type type : fieldTypes) {
                 final String fieldName = getFieldName(i, type);
                 classEmitter.field(fieldName, type.getTypeClass());
 
@@ -532,13 +534,10 @@
     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;
@@ -556,7 +555,7 @@
         final boolean isPrimitiveStorage = forType != null && forType.isPrimitive();
 
         //which is the primordial getter
-        final MethodHandle getter = OBJECT_FIELDS_ONLY ? objectGetter : isPrimitiveStorage ? primitiveGetter : objectGetter;
+        final MethodHandle getter = primitiveGetter == null ? objectGetter : isPrimitiveStorage ? primitiveGetter : objectGetter;
 
         if (forType == null) {
             if (isOptimistic) {
@@ -579,8 +578,7 @@
             return MH.dropArguments(GET_UNDEFINED.get(ti), 0, Object.class);
         }
 
-        assert forType != null;
-        assert !OBJECT_FIELDS_ONLY || forType == Object.class : forType;
+        assert primitiveGetter != null || forType == Object.class : forType;
 
         if (isOptimistic) {
             if (fti < ti) {
@@ -634,8 +632,6 @@
             return tgetter;
         }
 
-        assert !OBJECT_FIELDS_ONLY;
-        //final MethodType pmt = primitiveGetter.type();
         assert primitiveGetter != null;
         final MethodType tgetterType = tgetter.type();
         switch (fti) {
@@ -726,7 +722,7 @@
         final int fti = getAccessorTypeIndex(forType);
         final int ti  = getAccessorTypeIndex(type);
 
-        if (fti == TYPE_OBJECT_INDEX || OBJECT_FIELDS_ONLY) {
+        if (fti == TYPE_OBJECT_INDEX || primitiveSetter == null) {
             if (ti == TYPE_OBJECT_INDEX) {
                 return objectSetter;
             }
@@ -734,8 +730,6 @@
             return MH.asType(objectSetter, objectSetter.type().changeParameterType(1, type));
         }
 
-        assert !OBJECT_FIELDS_ONLY;
-
         final MethodType pmt = primitiveSetter.type();
 
         switch (fti) {
@@ -792,7 +786,7 @@
      * @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
+     * @return method handle that checks if the element to be set is of the current type, 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
      */
@@ -826,44 +820,13 @@
     }
 
     /**
-     * Describes the allocator class name and property map for a constructor function with the specified
+     * Creates the allocator class name and property map for a constructor function with the specified
      * number of "this" properties that it initializes.
-     *
+     * @param thisProperties number of properties assigned to "this"
+     * @return the allocation strategy
      */
-    public static class AllocatorDescriptor {
-        private final String allocatorClassName;
-        private final PropertyMap allocatorMap;
-
-        /**
-         * Creates a new allocator descriptor
-         * @param thisProperties the number of "this" properties that the function initializes
-         */
-        public AllocatorDescriptor(final int thisProperties) {
-            final int paddedFieldCount = getPaddedFieldCount(thisProperties);
-            this.allocatorClassName = Compiler.binaryName(getClassName(paddedFieldCount));
-            this.allocatorMap = PropertyMap.newMap(null, allocatorClassName, 0, paddedFieldCount, 0);
-        }
-
-        /**
-         * Returns the name of the class that the function allocates
-         * @return the name of the class that the function allocates
-         */
-        public String getAllocatorClassName() {
-            return allocatorClassName;
-        }
-
-        /**
-         * Returns the allocator map for the function.
-         * @return the allocator map for the function.
-         */
-        public PropertyMap getAllocatorMap() {
-            return allocatorMap;
-        }
-
-        @Override
-        public String toString() {
-            return "AllocatorDescriptor[allocatorClassName=" + allocatorClassName + ", allocatorMap.size=" +
-                    allocatorMap.size() + "]";
-        }
+    static AllocationStrategy createAllocationStrategy(final int thisProperties, final boolean dualFields) {
+        final int paddedFieldCount = getPaddedFieldCount(thisProperties);
+        return new AllocationStrategy(paddedFieldCount, dualFields);
     }
 }
diff --git a/src/jdk/nashorn/internal/codegen/ObjectCreator.java b/src/jdk/nashorn/internal/codegen/ObjectCreator.java
index 1a09ca6..0446c07 100644
--- a/src/jdk/nashorn/internal/codegen/ObjectCreator.java
+++ b/src/jdk/nashorn/internal/codegen/ObjectCreator.java
@@ -36,7 +36,7 @@
  * Base class for object creation code generation.
  * @param <T> value type
  */
-public abstract class ObjectCreator<T> {
+public abstract class ObjectCreator<T> implements CodeGenerator.SplitLiteralCreator {
 
     /** List of keys & symbols to initiate in this ObjectCreator */
     final List<MapTuple<T>> tuples;
@@ -69,7 +69,23 @@
      * Generate code for making the object.
      * @param method Script method.
      */
-    protected abstract void makeObject(final MethodEmitter method);
+    public void makeObject(final MethodEmitter method) {
+        createObject(method);
+        // We need to store the object in a temporary slot as populateRange expects to load the
+        // object from a slot (as it is also invoked within split methods). Note that this also
+        // helps optimistic continuations to handle the stack in case an optimistic assumption
+        // fails during initialization (see JDK-8079269).
+        final int objectSlot = method.getUsedSlotsWithLiveTemporaries();
+        final Type objectType = method.peekType();
+        method.storeTemp(objectType, objectSlot);
+        populateRange(method, objectType, objectSlot, 0, tuples.size());
+    }
+
+    /**
+     * Generate code for creating and initializing the object.
+     * @param method the method emitter
+     */
+    protected abstract void createObject(final MethodEmitter method);
 
     /**
      * Construct the property map appropriate for the object.
@@ -125,6 +141,12 @@
     }
 
     /**
+     * Get the class of objects created by this ObjectCreator
+     * @return class of created object
+     */
+    abstract protected Class<? extends ScriptObject> getAllocatorClass();
+
+    /**
      * Technique for loading an initial value. Defined by anonymous subclasses in code gen.
      *
      * @param value Value to load.
@@ -134,7 +156,7 @@
 
     MethodEmitter loadTuple(final MethodEmitter method, final MapTuple<T> tuple, final boolean pack) {
         loadValue(tuple.value, tuple.type);
-        if (pack && tuple.isPrimitive()) {
+        if (pack && codegen.useDualFields() && tuple.isPrimitive()) {
             method.pack();
         } else {
             method.convert(Type.OBJECT);
@@ -145,5 +167,4 @@
     MethodEmitter loadTuple(final MethodEmitter method, final MapTuple<T> tuple) {
         return loadTuple(method, tuple, true);
     }
-
 }
diff --git a/src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java b/src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java
index c802907..275bf5c 100644
--- a/src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java
+++ b/src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java
@@ -38,12 +38,10 @@
 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;
@@ -53,7 +51,7 @@
 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.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.parser.TokenType;
 import jdk.nashorn.internal.runtime.ScriptObject;
 
@@ -62,7 +60,7 @@
  * 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 class OptimisticTypesCalculator extends SimpleNodeVisitor {
 
     final Compiler compiler;
 
@@ -70,7 +68,6 @@
     final Deque<BitSet> neverOptimistic = new ArrayDeque<>();
 
     OptimisticTypesCalculator(final Compiler compiler) {
-        super(new LexicalContext());
         this.compiler = compiler;
     }
 
@@ -208,7 +205,7 @@
     @Override
     public Node leaveFunctionNode(final FunctionNode functionNode) {
         neverOptimistic.pop();
-        return functionNode.setState(lc, CompilationState.OPTIMISTIC_TYPES_ASSIGNED);
+        return functionNode;
     }
 
     @Override
diff --git a/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java b/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java
index 53a107e..9eb23bd 100644
--- a/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java
+++ b/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java
@@ -61,7 +61,7 @@
 import jdk.nashorn.internal.runtime.options.Options;
 
 /**
- * Static utility that encapsulates persistence of type information for functions compiled with optimistic
+ * <p>Static utility that encapsulates persistence of type information for functions compiled with optimistic
  * typing. With this feature enabled, when a JavaScript function is recompiled because it gets deoptimized,
  * the type information for deoptimization is stored in a cache file. If the same function is compiled in a
  * subsequent JVM invocation, the type information is used for initial compilation, thus allowing the system
@@ -77,6 +77,7 @@
  * {@code nashorn.typeInfo.cleanupDelaySeconds} system property. You can also specify the word
  * {@code unlimited} as the value for {@code nashorn.typeInfo.maxFiles} in which case the type info cache is
  * allowed to grow without limits.
+ * </p>
  */
 public final class OptimisticTypesPersistence {
     // Default is 0, for disabling the feature when not specified. A reasonable default when enabled is
diff --git a/src/jdk/nashorn/internal/codegen/ProgramPoints.java b/src/jdk/nashorn/internal/codegen/ProgramPoints.java
index 4606989..bfc47ea 100644
--- a/src/jdk/nashorn/internal/codegen/ProgramPoints.java
+++ b/src/jdk/nashorn/internal/codegen/ProgramPoints.java
@@ -37,25 +37,20 @@
 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;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 
 /**
  * Find program points in the code that are needed for optimistic assumptions
  */
-class ProgramPoints extends NodeVisitor<LexicalContext> {
+class ProgramPoints extends SimpleNodeVisitor {
 
     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) {
diff --git a/src/jdk/nashorn/internal/codegen/ReplaceCompileUnits.java b/src/jdk/nashorn/internal/codegen/ReplaceCompileUnits.java
index 57f9e68..594ba66 100644
--- a/src/jdk/nashorn/internal/codegen/ReplaceCompileUnits.java
+++ b/src/jdk/nashorn/internal/codegen/ReplaceCompileUnits.java
@@ -29,21 +29,17 @@
 import java.util.List;
 import jdk.nashorn.internal.ir.CompileUnitHolder;
 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.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.ObjectNode;
+import jdk.nashorn.internal.ir.Splittable;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 
 /**
  * Base class for a node visitor that replaces {@link CompileUnit}s in {@link CompileUnitHolder}s.
  */
-abstract class ReplaceCompileUnits extends NodeVisitor<LexicalContext> {
-    ReplaceCompileUnits() {
-        super(new LexicalContext());
-    }
+abstract class ReplaceCompileUnits extends SimpleNodeVisitor {
 
     /**
      * Override to provide a replacement for an old compile unit.
@@ -64,22 +60,35 @@
 
     @Override
     public Node leaveFunctionNode(final FunctionNode node) {
-        return node.setCompileUnit(lc, getExistingReplacement(node)).setState(lc, CompilationState.COMPILE_UNITS_REUSED);
+        return node.setCompileUnit(lc, getExistingReplacement(node));
     }
 
     @Override
     public Node leaveLiteralNode(final LiteralNode<?> node) {
         if (node instanceof ArrayLiteralNode) {
             final ArrayLiteralNode aln = (ArrayLiteralNode)node;
-            if (aln.getUnits() == null) {
+            if (aln.getSplitRanges() == null) {
                 return node;
             }
-            final List<ArrayUnit> newArrayUnits = new ArrayList<>();
-            for (final ArrayUnit au : aln.getUnits()) {
-                newArrayUnits.add(new ArrayUnit(getExistingReplacement(au), au.getLo(), au.getHi()));
+            final List<Splittable.SplitRange> newArrayUnits = new ArrayList<>();
+            for (final Splittable.SplitRange au : aln.getSplitRanges()) {
+                newArrayUnits.add(new Splittable.SplitRange(getExistingReplacement(au), au.getLow(), au.getHigh()));
             }
-            return aln.setUnits(lc, newArrayUnits);
+            return aln.setSplitRanges(lc, newArrayUnits);
         }
         return node;
     }
+
+    @Override
+    public Node leaveObjectNode(final ObjectNode objectNode) {
+        final List<Splittable.SplitRange> ranges = objectNode.getSplitRanges();
+        if (ranges != null) {
+            final List<Splittable.SplitRange> newRanges = new ArrayList<>();
+            for (final Splittable.SplitRange range : ranges) {
+                newRanges.add(new Splittable.SplitRange(getExistingReplacement(range), range.getLow(), range.getHigh()));
+            }
+            return objectNode.setSplitRanges(lc, newRanges);
+        }
+        return super.leaveObjectNode(objectNode);
+    }
 }
diff --git a/src/jdk/nashorn/internal/codegen/RuntimeCallSite.java b/src/jdk/nashorn/internal/codegen/RuntimeCallSite.java
deleted file mode 100644
index b4d2f2d..0000000
--- a/src/jdk/nashorn/internal/codegen/RuntimeCallSite.java
+++ /dev/null
@@ -1,683 +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.staticCallNoLookup;
-import static jdk.nashorn.internal.codegen.types.Type.BOOLEAN;
-import static jdk.nashorn.internal.codegen.types.Type.INT;
-import static jdk.nashorn.internal.lookup.Lookup.MH;
-
-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.util.HashMap;
-import java.util.Map;
-import jdk.nashorn.internal.codegen.CompilerConstants.Call;
-import jdk.nashorn.internal.codegen.types.Type;
-import jdk.nashorn.internal.ir.RuntimeNode;
-import jdk.nashorn.internal.ir.RuntimeNode.Request;
-import jdk.nashorn.internal.lookup.Lookup;
-import jdk.nashorn.internal.runtime.ScriptRuntime;
-import jdk.nashorn.internal.runtime.linker.Bootstrap;
-
-/**
- * Optimistic call site that assumes its Object arguments to be of a boxed type.
- * Gradually reverts to wider boxed types if the assumption for the RuntimeNode
- * is proven wrong. Finally reverts to the generic ScriptRuntime method.
- *
- * This is used from the CodeGenerator when we have a runtime node, but 1 or more
- * primitive arguments. This class generated appropriate specializations, for example
- * {@code Object a === int b} is a good idea to specialize to {@code ((Integer)a).intValue() == b}
- * surrounded by catch blocks that will try less narrow specializations
- */
-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_V("next",  MethodHandle.class, String.class);
-
-    private final RuntimeNode.Request request;
-
-    /**
-     * A specialized runtime node, i.e. on where we know at least one more specific type than object
-     */
-    static final class SpecializedRuntimeNode {
-        private static final char REQUEST_SEPARATOR = ':';
-
-        private final RuntimeNode.Request request;
-
-        private final Type[] parameterTypes;
-
-        private final Type   returnType;
-
-        /**
-         * Constructor.
-         *
-         * @param request        runtime node request to specialize
-         * @param parameterTypes parameter types of the call site
-         * @param returnType     return type of the call site
-         */
-        SpecializedRuntimeNode(final RuntimeNode.Request request, final Type[] parameterTypes, final Type returnType) {
-            this.request        = request;
-            this.parameterTypes = parameterTypes;
-            this.returnType     = returnType;
-        }
-
-        /**
-         * The first type to try to use for this generated runtime node
-         *
-         * @return a type
-         */
-        public Type firstTypeGuess() {
-            Type widest = Type.UNKNOWN;
-            for (final Type type : parameterTypes) {
-                if (type.isObject()) {
-                    continue;
-                }
-                widest = Type.widest(type, widest);
-            }
-            widest = Type.widest(widest, firstTypeGuessForObject(request));
-
-            return widest;
-        }
-
-        private static Type firstTypeGuessForObject(final Request request) {
-            switch (request) {
-            case ADD:
-                return INT;
-            default:
-                return BOOLEAN;
-            }
-        }
-
-        Request getRequest() {
-            return request;
-        }
-
-        Type[] getParameterTypes() {
-            return parameterTypes;
-        }
-
-        Type getReturnType() {
-            return returnType;
-        }
-
-        private static char descFor(final Type type) {
-            if (type.isObject()) {
-                return 'O';
-            }
-            return type.getDescriptor().charAt(0);
-        }
-
-        @Override
-        public boolean equals(final Object other) {
-            if (other instanceof SpecializedRuntimeNode) {
-                final SpecializedRuntimeNode otherNode = (SpecializedRuntimeNode)other;
-
-                if (!otherNode.getReturnType().equals(getReturnType())) {
-                    return false;
-                }
-
-                if (getParameterTypes().length != otherNode.getParameterTypes().length) {
-                    return false;
-                }
-
-                for (int i = 0; i < getParameterTypes().length; i++) {
-                    if (!Type.areEquivalent(getParameterTypes()[i], otherNode.getParameterTypes()[i])) {
-                        return false;
-                    }
-                }
-
-                return otherNode.getRequest().equals(getRequest());
-            }
-
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            int hashCode = getRequest().toString().hashCode();
-            hashCode ^= getReturnType().hashCode();
-            for (final Type type : getParameterTypes()) {
-                hashCode ^= type.hashCode();
-            }
-            return hashCode;
-        }
-
-        @Override
-        public String toString() {
-            final StringBuilder sb = new StringBuilder();
-            sb.append(getRequest().toString());
-            sb.append(REQUEST_SEPARATOR);
-            sb.append(descFor(getReturnType()));
-
-            for (final Type type : getParameterTypes()) {
-                sb.append(descFor(type));
-            }
-
-            return sb.toString();
-        }
-
-        String getName(final Type extraType) {
-            return toString() + "_" + descFor(extraType);
-        }
-
-        String getInitialName() {
-            return getName(firstTypeGuess());
-        }
-    }
-
-
-    /**
-     * Constructor
-     *
-     * @param type method type for call site
-     * @param name name of runtime call
-     */
-    public RuntimeCallSite(final MethodType type, final String name) {
-        super(type);
-        this.request = Request.valueOf(name.substring(0, name.indexOf(SpecializedRuntimeNode.REQUEST_SEPARATOR)));
-        setTarget(makeMethod(name));
-    }
-
-    private String nextName(final String requestName) {
-        if (requestName.equals(request.toString())) {
-            return null;
-        }
-
-        final char[] c = requestName.toCharArray();
-        final int last = c.length - 1;
-
-        if (c[last - 1] != '_') {
-            return null;
-        }
-
-        switch (c[last]) {
-        case 'Z':
-            c[last] = 'I';
-            break;
-        case 'I':
-            c[last] = 'J';
-            break;
-        case 'J':
-            c[last] = 'D';
-            break;
-        case 'D':
-        default:
-            return request.toString();
-        }
-
-        return new String(c);
-    }
-
-    private boolean isSpecialized(final String requestName) {
-        return nextName(requestName) != null;
-    }
-
-    private MethodHandle makeMethod(final String requestName) {
-        MethodHandle mh;
-
-        if (isSpecialized(requestName)) {
-            final Class<?> boxedType;
-            final Class<?> primitiveType;
-
-            switch (requestName.charAt(requestName.length() - 1)) {
-            case 'Z':
-                boxedType = Boolean.class;
-                primitiveType = int.class;
-                break;
-            case 'I':
-                boxedType = Integer.class;
-                primitiveType = int.class;
-                break;
-            case 'J':
-                boxedType = Long.class;
-                primitiveType = long.class;
-                break;
-            case 'D':
-                boxedType = Number.class;
-                primitiveType = double.class;
-                break;
-            default:
-                throw new RuntimeException("should not reach here");
-            }
-
-            final boolean isStrictCmp = (request == Request.EQ_STRICT || request == Request.NE_STRICT);
-
-            if (isStrictCmp &&
-                    (boxedType != Boolean.class &&
-                        (type().parameterType(0) == boolean.class ||
-                         type().parameterType(1) == boolean.class))) {
-                // number and boolean are never strictly equal, e.g. 0 !== false
-                mh = MH.dropArguments(MH.constant(boolean.class, request == Request.NE_STRICT), 0, type().parameterArray());
-            } else {
-                mh = METHODS.get(request.nonStrictName() + primitiveType.getSimpleName());
-                // unbox objects
-
-                for (int i = 0; i < type().parameterCount(); i++) {
-                    if (!type().parameterType(i).isPrimitive()) {
-                        mh = MH.filterArguments(mh, i, UNBOX.get(boxedType));
-                    }
-                }
-
-                mh = Lookup.filterReturnType(mh, type().returnType());
-                mh = MH.explicitCastArguments(mh, type());
-            }
-
-            final MethodHandle fallback = MH.foldArguments(MethodHandles.exactInvoker(type()), MH.insertArguments(NEXT, 0, this, requestName));
-
-            MethodHandle guard;
-            if (type().parameterType(0).isPrimitive()) {
-                guard = MH.insertArguments(
-                            MH.dropArguments(CHECKCAST, 1, type().parameterType(0)), 0, boxedType);
-            } else if (type().parameterType(1).isPrimitive()) {
-                guard = MH.insertArguments(
-                            MH.dropArguments(CHECKCAST, 2, type().parameterType(1)), 0, boxedType);
-            } else {
-                assert !type().parameterType(0).isPrimitive() && !type().parameterType(1).isPrimitive();
-                guard = MH.insertArguments(CHECKCAST2, 0, boxedType);
-            }
-
-            if (request == Request.ADD && boxedType == Integer.class) {
-                // int add needs additional overflow check
-                MethodHandle addcheck = ADDCHECK;
-                for (int i = 0; i < type().parameterCount(); i++) {
-                    if (!type().parameterType(i).isPrimitive()) {
-                        addcheck = MH.filterArguments(addcheck, i, UNBOX.get(boxedType));
-                    }
-                }
-                addcheck = MH.explicitCastArguments(addcheck, type().changeReturnType(boolean.class));
-                guard    = MH.guardWithTest(upcastGuard(guard), addcheck,
-                                MH.dropArguments(MH.constant(boolean.class, false), 0, type().parameterArray()));
-            }
-
-            return MH.guardWithTest(upcastGuard(guard), mh, fallback);
-        }
-
-        // generic fallback
-        return MH.explicitCastArguments(Lookup.filterReturnType(GENERIC_METHODS.get(request.name()), type().returnType()), type());
-    }
-
-    private MethodHandle upcastGuard(final MethodHandle guard) {
-        return MH.asType(guard, type().changeReturnType(boolean.class));
-    }
-
-    /**
-     * This is public just so that the generated specialization code can
-     * use it to get the next wider typed method
-     *
-     * Do not call directly
-     *
-     * @param name current name (with type) of runtime call at the call site
-     * @return next wider specialization method for this RuntimeCallSite
-     */
-   public MethodHandle next(final String name) {
-        final MethodHandle next = makeMethod(nextName(name));
-        setTarget(next);
-        return next;
-    }
-
-    /** Method cache */
-    private static final Map<String, MethodHandle> METHODS;
-
-    /** Generic method cache */
-    private static final Map<String, MethodHandle> GENERIC_METHODS;
-
-    /** Unbox cache */
-    private static final Map<Class<?>, MethodHandle> UNBOX;
-
-    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_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<>();
-
-        for (final Request req : Request.values()) {
-            if (req.canSpecialize()) {
-                if (req.name().endsWith("_STRICT")) {
-                    continue;
-                }
-
-                final boolean isCmp = Request.isComparison(req);
-
-                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));
-            }
-        }
-
-        GENERIC_METHODS = new HashMap<>();
-        for (final Request req : Request.values()) {
-            if (req.canSpecialize()) {
-                GENERIC_METHODS.put(req.name(), MH.findStatic(MethodHandles.lookup(), ScriptRuntime.class, req.name(),
-                        MH.type(req.getReturnType().getTypeClass(), Object.class, Object.class)));
-            }
-        }
-    }
-
-    /**
-     * Specialized version of != operator for two int arguments. Do not call directly.
-     * @param a int
-     * @param b int
-     * @return a != b
-     */
-    public static boolean NE(final int a, final int b) {
-        return a != b;
-    }
-
-    /**
-     * Specialized version of != operator for two double arguments. Do not call directly.
-     * @param a double
-     * @param b double
-     * @return a != b
-     */
-    public static boolean NE(final double a, final double b) {
-        return a != b;
-    }
-
-    /**
-     * Specialized version of != operator for two long arguments. Do not call directly.
-     * @param a long
-     * @param b long
-     * @return a != b
-     */
-    public static boolean NE(final long a, final long b) {
-        return a != b;
-    }
-
-    /**
-     * Specialized version of == operator for two int arguments. Do not call directly.
-     * @param a int
-     * @param b int
-     * @return a == b
-     */
-    public static boolean EQ(final int a, final int b) {
-        return a == b;
-    }
-
-    /**
-     * Specialized version of == operator for two double arguments. Do not call directly.
-     * @param a double
-     * @param b double
-     * @return a == b
-     */
-    public static boolean EQ(final double a, final double b) {
-        return a == b;
-    }
-
-    /**
-     * Specialized version of == operator for two long arguments. Do not call directly.
-     * @param a long
-     * @param b long
-     * @return a == b
-     */
-    public static boolean EQ(final long a, final long b) {
-        return a == b;
-    }
-
-    /**
-     * Specialized version of {@literal <} operator for two int arguments. Do not call directly.
-     * @param a int
-     * @param b int
-     * @return a {@code <} b
-     */
-    public static boolean LT(final int a, final int b) {
-        return a < b;
-    }
-
-    /**
-     * Specialized version of {@literal <} operator for two double arguments. Do not call directly.
-     * @param a double
-     * @param b double
-     * @return a {@literal <} b
-     */
-    public static boolean LT(final double a, final double b) {
-        return a < b;
-    }
-
-    /**
-     * Specialized version of {@literal <} operator for two long arguments. Do not call directly.
-     * @param a long
-     * @param b long
-     * @return a {@literal <} b
-     */
-    public static boolean LT(final long a, final long b) {
-        return a < b;
-    }
-
-    /**
-     * Specialized version of {@literal <=} operator for two int arguments. Do not call directly.
-     * @param a int
-     * @param b int
-     * @return a {@literal <=} b
-     */
-    public static boolean LE(final int a, final int b) {
-        return a <= b;
-    }
-
-    /**
-     * Specialized version of {@literal <=} operator for two double arguments. Do not call directly.
-     * @param a double
-     * @param b double
-     * @return a {@literal <=} b
-     */
-    public static boolean LE(final double a, final double b) {
-        return a <= b;
-    }
-
-    /**
-     * Specialized version of {@literal <=} operator for two long arguments. Do not call directly.
-     * @param a long
-     * @param b long
-     * @return a {@literal <=} b
-     */
-    public static boolean LE(final long a, final long b) {
-        return a <= b;
-    }
-
-    /**
-     * Specialized version of {@literal >} operator for two int arguments. Do not call directly.
-     * @param a int
-     * @param b int
-     * @return a {@literal >} b
-     */
-    public static boolean GT(final int a, final int b) {
-        return a > b;
-    }
-
-    /**
-     * Specialized version of {@literal >} operator for two double arguments. Do not call directly.
-     * @param a double
-     * @param b double
-     * @return a {@literal >} b
-     */
-    public static boolean GT(final double a, final double b) {
-        return a > b;
-    }
-
-    /**
-     * Specialized version of {@literal >} operator for two long arguments. Do not call directly.
-     * @param a long
-     * @param b long
-     * @return a {@literal >} b
-     */
-    public static boolean GT(final long a, final long b) {
-        return a > b;
-    }
-
-    /**
-     * Specialized version of {@literal >=} operator for two int arguments. Do not call directly.
-     * @param a int
-     * @param b int
-     * @return a {@literal >=} b
-     */
-    public static boolean GE(final int a, final int b) {
-        return a >= b;
-    }
-
-    /**
-     * Specialized version of {@literal >=} operator for two double arguments. Do not call directly.
-     * @param a double
-     * @param b double
-     * @return a {@literal >=} b
-     */
-    public static boolean GE(final double a, final double b) {
-        return a >= b;
-    }
-
-    /**
-     * Specialized version of {@literal >=} operator for two long arguments. Do not call directly.
-     * @param a long
-     * @param b long
-     * @return a {@code >=} b
-     */
-    public static boolean GE(final long a, final long b) {
-        return a >= b;
-    }
-
-    /**
-     * Specialized version of + operator for two int arguments. Do not call directly.
-     * @param a int
-     * @param b int
-     * @return a + b
-     */
-    public static int ADD(final int a, final int b) {
-        return a + b;
-    }
-
-    /**
-     * Specialized version of + operator for two long arguments. Do not call directly.
-     * @param a long
-     * @param b long
-     * @return a + b
-     */
-    public static long ADD(final long a, final long b) {
-        return a + b;
-    }
-
-    /**
-     * Specialized version of + operator for two double arguments. Do not call directly.
-     * @param a double
-     * @param b double
-     * @return a + b
-     */
-    public static double ADD(final double a, final double b) {
-        return a + b;
-    }
-
-    /**
-     * Check that ints are addition compatible, i.e. their sum is equal to the sum
-     * of them cast to long. Otherwise the addition will overflow. Do not call directly.
-     *
-     * @param a int
-     * @param b int
-     *
-     * @return true if addition does not overflow
-     */
-    public static boolean ADDcheck(final int a, final int b) {
-        return (a + b == (long)a + (long)b);
-    }
-
-    /**
-     * Checkcast used for specialized ops. Do not call directly
-     *
-     * @param type to to check against
-     * @param obj  object to check for type
-     *
-     * @return true if type check holds
-     */
-    public static boolean checkcast(final Class<?> type, final Object obj) {
-        return type.isInstance(obj);
-    }
-
-    /**
-     * Checkcast used for specialized ops. Do not call directly
-     *
-     * @param type type to check against
-     * @param objA first object to check against type
-     * @param objB second object to check against type
-     *
-     * @return true if type check holds for both objects
-     */
-    public static boolean checkcast(final Class<?> type, final Object objA, final Object objB) {
-        return type.isInstance(objA) && type.isInstance(objB);
-    }
-
-    /**
-     * Unbox a java.lang.Boolean. Do not call directly
-     * @param obj object to cast to int and unbox
-     * @return an int value for the boolean, 1 is true, 0 is false
-     */
-    public static int unboxZ(final Object obj) {
-        return (boolean)obj ? 1 : 0;
-    }
-
-    /**
-     * Unbox a java.lang.Integer. Do not call directly
-     * @param obj object to cast to int and unbox
-     * @return an int
-     */
-    public static int unboxI(final Object obj) {
-        return (int)obj;
-    }
-
-    /**
-     * Unbox a java.lang.Long. Do not call directly
-     * @param obj object to cast to long and unbox
-     * @return a long
-     */
-    public static long unboxJ(final Object obj) {
-        return (long)obj;
-    }
-
-    /**
-     * Unbox a java.lang.Number. Do not call directly
-     * @param obj object to cast to Number and unbox
-     * @return a double
-     */
-    public static double unboxD(final Object obj) {
-        return ((Number)obj).doubleValue();
-    }
-
-    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/src/jdk/nashorn/internal/codegen/SharedScopeCall.java b/src/jdk/nashorn/internal/codegen/SharedScopeCall.java
index 078324c..eb4758f 100644
--- a/src/jdk/nashorn/internal/codegen/SharedScopeCall.java
+++ b/src/jdk/nashorn/internal/codegen/SharedScopeCall.java
@@ -169,7 +169,7 @@
                 slot += type.getSlots();
             }
             // Shared scope calls disabled in optimistic world. TODO is this right?
-            method.dynamicCall(returnType, 2 + paramTypes.length, flags);
+            method.dynamicCall(returnType, 2 + paramTypes.length, flags, symbol.getName());
         }
 
         method._return(returnType);
diff --git a/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java b/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java
index 40d12df..9cda8dd 100644
--- a/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java
+++ b/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java
@@ -27,7 +27,6 @@
 
 import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup;
 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
 
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -42,6 +41,7 @@
 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.JD;
 import jdk.nashorn.internal.scripts.JO;
 
 /**
@@ -61,14 +61,15 @@
     }
 
     @Override
-    protected void makeObject(final MethodEmitter method) {
+    public void createObject(final MethodEmitter method) {
         assert !isScope() : "spill scope objects are not currently supported";
 
         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();
+        final boolean      dualFields    = codegen.useDualFields();
+        final int          spillLength   = ScriptObject.spillAllocationLength(length);
+        final long[]       jpresetValues = dualFields ? new long[spillLength] : null;
+        final Object[]     opresetValues = new Object[spillLength];
+        final Class<?>     objectClass   = getAllocatorClass();
         ArrayData          arrayData     = ArrayData.allocate(ScriptRuntime.EMPTY_ARRAY);
 
         // Compute constant property values
@@ -82,15 +83,13 @@
 
             if (value != null) {
                 final Object constantValue = LiteralNode.objectAsConstant(value);
-                if (constantValue == LiteralNode.POSTSET_MARKER) {
-                    postsetValues.add(pos);
-                } else {
+                if (constantValue != LiteralNode.POSTSET_MARKER) {
                     final Property property = propertyMap.findProperty(key);
                     if (property != null) {
                         // normal property key
-                        property.setType(JSType.unboxedFieldType(constantValue));
+                        property.setType(dualFields ? JSType.unboxedFieldType(constantValue) : Object.class);
                         final int slot = property.getSlot();
-                        if (!OBJECT_FIELDS_ONLY && constantValue instanceof Number) {
+                        if (dualFields && constantValue instanceof Number) {
                             jpresetValues[slot] = ObjectClassGenerator.pack((Number)constantValue);
                         } else {
                             opresetValues[slot] = constantValue;
@@ -127,40 +126,21 @@
             pos++;
         }
 
-        //assert postsetValues.isEmpty() : "test me " + postsetValues;
-
         // create object and invoke constructor
-        method._new(JO.class).dup();
+        method._new(objectClass).dup();
         codegen.loadConstant(propertyMap);
 
-        //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();
-            }
+        // load primitive value spill array
+        if (dualFields) {
+            codegen.loadConstant(jpresetValues);
+        } else {
+            method.loadNull();
         }
-
-        //load object values to o spill array
+        // load object value 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));
+        // instantiate the script object with spill objects
+        method.invoke(constructorNoLookup(objectClass, PropertyMap.class, long[].class, Object[].class));
 
         // Set prefix array data if any
         if (arrayData.length() > 0) {
@@ -168,19 +148,34 @@
             codegen.loadConstant(arrayData);
             method.invoke(virtualCallNoLookup(ScriptObject.class, "setArray", void.class, ArrayData.class));
         }
+    }
 
-        // set postfix
-        for (final int i : postsetValues) {
-            final MapTuple<Expression> tuple    = tuples.get(i);
-            final Property             property = propertyMap.findProperty(tuple.key);
+    @Override
+    public void populateRange(final MethodEmitter method, final Type objectType, final int objectSlot, final int start, final int end) {
+        final int  callSiteFlags = codegen.getCallSiteFlags();
+        method.load(objectType, objectSlot);
+
+        // set postfix values
+        for (int i = start; i < end; i++) {
+            final MapTuple<Expression> tuple = tuples.get(i);
+
+            if (LiteralNode.isConstant(tuple.value)) {
+                continue;
+            }
+
+            final Property property = propertyMap.findProperty(tuple.key);
+
             if (property == null) {
                 final int index = ArrayIndex.getArrayIndex(tuple.key);
                 assert ArrayIndex.isValidArrayIndex(index);
                 method.dup();
                 method.load(ArrayIndex.toLongIndex(index));
-                //method.println("putting " + tuple + " into arraydata");
                 loadTuple(method, tuple);
                 method.dynamicSetIndex(callSiteFlags);
+            } else {
+                method.dup();
+                loadTuple(method, tuple);
+                method.dynamicSet(property.getKey(), codegen.getCallSiteFlags(), false);
             }
         }
     }
@@ -188,7 +183,8 @@
     @Override
     protected PropertyMap makeMap() {
         assert propertyMap == null : "property map already initialized";
-        propertyMap = new MapCreator<>(JO.class, tuples).makeSpillMap(false);
+        final Class<? extends ScriptObject> clazz = getAllocatorClass();
+        propertyMap = new MapCreator<>(clazz, tuples).makeSpillMap(false, codegen.useDualFields());
         return propertyMap;
     }
 
@@ -196,4 +192,9 @@
     protected void loadValue(final Expression expr, final Type type) {
         codegen.loadExpressionAsType(expr, type);
     }
+
+    @Override
+    protected Class<? extends ScriptObject> getAllocatorClass() {
+        return codegen.useDualFields() ? JD.class : JO.class;
+    }
 }
diff --git a/src/jdk/nashorn/internal/codegen/SplitIntoFunctions.java b/src/jdk/nashorn/internal/codegen/SplitIntoFunctions.java
index 9933274..019815a 100644
--- a/src/jdk/nashorn/internal/codegen/SplitIntoFunctions.java
+++ b/src/jdk/nashorn/internal/codegen/SplitIntoFunctions.java
@@ -51,6 +51,7 @@
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.IfNode;
 import jdk.nashorn.internal.ir.JumpStatement;
+import jdk.nashorn.internal.ir.JumpToInlinedFinally;
 import jdk.nashorn.internal.ir.LiteralNode;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.ReturnNode;
@@ -100,7 +101,7 @@
     public SplitIntoFunctions(final Compiler compiler) {
         super(new BlockLexicalContext() {
             @Override
-            protected Block afterSetStatements(Block block) {
+            protected Block afterSetStatements(final Block block) {
                 for(Statement stmt: block.getStatements()) {
                     assert !(stmt instanceof SplitNode);
                 }
@@ -174,8 +175,7 @@
                 FunctionNode.IS_ANONYMOUS | FunctionNode.USES_ANCESTOR_SCOPE | FunctionNode.IS_SPLIT
         )
         .setBody(lc, body)
-        .setCompileUnit(lc, splitNode.getCompileUnit())
-        .copyCompilationState(lc, originalFn);
+        .setCompileUnit(lc, splitNode.getCompileUnit());
 
         // Call the function:
         //     either "(function () { ... }).call(this)"
@@ -300,17 +300,13 @@
     }
 
     @Override
-    public boolean enterVarNode(VarNode varNode) {
+    public boolean enterVarNode(final VarNode varNode) {
         if (!inSplitNode()) {
             return super.enterVarNode(varNode);
         }
         assert !varNode.isBlockScoped(); //TODO: we must handle these too, but we currently don't
 
         final Expression init = varNode.getInit();
-        if (varNode.isAnonymousFunctionDeclaration()) {
-            // We ain't moving anonymous function declarations.
-            return super.enterVarNode(varNode);
-        }
 
         // Move a declaration-only var statement to the top of the outermost function.
         getCurrentFunctionState().varStatements.add(varNode.setInit(null));
@@ -355,6 +351,11 @@
         return leaveJumpNode(continueNode);
     }
 
+    @Override
+    public Node leaveJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+        return leaveJumpNode(jumpToInlinedFinally);
+    }
+
     private JumpStatement leaveJumpNode(final JumpStatement jump) {
         if (inSplitNode()) {
             final SplitState splitState = getCurrentSplitState();
diff --git a/src/jdk/nashorn/internal/codegen/Splitter.java b/src/jdk/nashorn/internal/codegen/Splitter.java
index 9405d06..1fe97fe 100644
--- a/src/jdk/nashorn/internal/codegen/Splitter.java
+++ b/src/jdk/nashorn/internal/codegen/Splitter.java
@@ -33,22 +33,26 @@
 import java.util.Map;
 import jdk.nashorn.internal.ir.Block;
 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.ObjectNode;
+import jdk.nashorn.internal.ir.PropertyNode;
 import jdk.nashorn.internal.ir.SplitNode;
+import jdk.nashorn.internal.ir.Splittable;
 import jdk.nashorn.internal.ir.Statement;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
+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;
 
 /**
  * Split the IR into smaller compile units.
  */
-final class Splitter extends NodeVisitor<LexicalContext> {
+@Logger(name="splitter")
+final class Splitter extends SimpleNodeVisitor implements Loggable {
     /** Current compiler. */
     private final Compiler compiler;
 
@@ -74,11 +78,20 @@
      * @param outermostCompileUnit  compile unit for outermost function, if non-lazy this is the script's compile unit
      */
     public Splitter(final Compiler compiler, final FunctionNode functionNode, final CompileUnit outermostCompileUnit) {
-        super(new LexicalContext());
         this.compiler             = compiler;
         this.outermost            = functionNode;
         this.outermostCompileUnit = outermostCompileUnit;
-        this.log                  = compiler.getLogger();
+        this.log                  = initLogger(compiler.getContext());
+    }
+
+    @Override
+    public DebugLogger initLogger(final Context context) {
+        return context.getLogger(this.getClass());
+    }
+
+    @Override
+    public DebugLogger getLogger() {
+        return log;
     }
 
     /**
@@ -89,7 +102,7 @@
     FunctionNode split(final FunctionNode fn, final boolean top) {
         FunctionNode functionNode = fn;
 
-        log.finest("Initiating split of '", functionNode.getName(), "'");
+        log.fine("Initiating split of '", functionNode.getName(), "'");
 
         long weight = WeighNodes.weigh(functionNode);
 
@@ -98,7 +111,7 @@
         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.info("Splitting '", functionNode.getName(), "' as its weight ", weight, " exceeds split threshold ", SPLIT_THRESHOLD);
             functionNode = (FunctionNode)functionNode.accept(this);
 
             if (functionNode.isSplit()) {
@@ -127,7 +140,7 @@
         final Block body = functionNode.getBody();
         final List<FunctionNode> dc = directChildren(functionNode);
 
-        final Block newBody = (Block)body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        final Block newBody = (Block)body.accept(new SimpleNodeVisitor() {
             @Override
             public boolean enterFunctionNode(final FunctionNode nestedFunction) {
                 return dc.contains(nestedFunction);
@@ -144,12 +157,12 @@
 
         assert functionNode.getCompileUnit() != null;
 
-        return functionNode.setState(null, CompilationState.SPLIT);
+        return functionNode;
     }
 
     private static List<FunctionNode> directChildren(final FunctionNode functionNode) {
         final List<FunctionNode> dc = new ArrayList<>();
-        functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        functionNode.accept(new SimpleNodeVisitor() {
             @Override
             public boolean enterFunctionNode(final FunctionNode child) {
                 if (child == functionNode) {
@@ -282,7 +295,7 @@
             final ArrayLiteralNode arrayLiteralNode = (ArrayLiteralNode) literal;
             final Node[]           value            = arrayLiteralNode.getValue();
             final int[]            postsets         = arrayLiteralNode.getPostsets();
-            final List<ArrayUnit>  units            = new ArrayList<>();
+            final List<Splittable.SplitRange> ranges = new ArrayList<>();
 
             long totalWeight = 0;
             int  lo          = 0;
@@ -296,7 +309,7 @@
 
                 if (totalWeight >= SPLIT_THRESHOLD) {
                     final CompileUnit unit = compiler.findUnit(totalWeight - weight);
-                    units.add(new ArrayUnit(unit, lo, i));
+                    ranges.add(new Splittable.SplitRange(unit, lo, i));
                     lo = i;
                     totalWeight = weight;
                 }
@@ -304,16 +317,59 @@
 
             if (lo != postsets.length) {
                 final CompileUnit unit = compiler.findUnit(totalWeight);
-                units.add(new ArrayUnit(unit, lo, postsets.length));
+                ranges.add(new Splittable.SplitRange(unit, lo, postsets.length));
             }
 
-            return arrayLiteralNode.setUnits(lc, units);
+            return arrayLiteralNode.setSplitRanges(lc, ranges);
         }
 
         return literal;
     }
 
     @Override
+    public Node leaveObjectNode(final ObjectNode objectNode) {
+        long weight = WeighNodes.weigh(objectNode);
+
+        if (weight < SPLIT_THRESHOLD) {
+            return objectNode;
+        }
+
+        final FunctionNode functionNode = lc.getCurrentFunction();
+        lc.setFlag(functionNode, FunctionNode.IS_SPLIT);
+
+        final List<Splittable.SplitRange> ranges        = new ArrayList<>();
+        final List<PropertyNode>          properties    = objectNode.getElements();
+        final boolean                     isSpillObject = properties.size() > CodeGenerator.OBJECT_SPILL_THRESHOLD;
+        long totalWeight = 0;
+        int  lo          = 0;
+
+        for (int i = 0; i < properties.size(); i++) {
+
+            final PropertyNode property = properties.get(i);
+            final boolean isConstant = LiteralNode.isConstant(property.getValue());
+
+            if (!isConstant || !isSpillObject) {
+                weight = isConstant ? 0 : WeighNodes.weigh(property.getValue());
+                totalWeight += WeighNodes.AASTORE_WEIGHT + weight;
+
+                if (totalWeight >= SPLIT_THRESHOLD) {
+                    final CompileUnit unit = compiler.findUnit(totalWeight - weight);
+                    ranges.add(new Splittable.SplitRange(unit, lo, i));
+                    lo = i;
+                    totalWeight = weight;
+                }
+            }
+        }
+
+        if (lo != properties.size()) {
+            final CompileUnit unit = compiler.findUnit(totalWeight);
+            ranges.add(new Splittable.SplitRange(unit, lo, properties.size()));
+        }
+
+        return objectNode.setSplitRanges(lc, ranges);
+    }
+
+    @Override
     public boolean enterFunctionNode(final FunctionNode node) {
         //only go into the function node for this splitter. any subfunctions are rejected
         return node == outermost;
diff --git a/src/jdk/nashorn/internal/codegen/TypeEvaluator.java b/src/jdk/nashorn/internal/codegen/TypeEvaluator.java
index d5282a8..ba9d7fd 100644
--- a/src/jdk/nashorn/internal/codegen/TypeEvaluator.java
+++ b/src/jdk/nashorn/internal/codegen/TypeEvaluator.java
@@ -227,7 +227,8 @@
             // gradually introduce them as needed. An easy one would be to do the same for .call(this) idiom.
             final CallNode callExpr = (CallNode)expr;
             final Expression fnExpr = callExpr.getFunction();
-            if (fnExpr instanceof FunctionNode) {
+            // Skip evaluation if running with eager compilation as we may violate constraints in RecompilableScriptFunctionData
+            if (fnExpr instanceof FunctionNode && compiler.getContext().getEnv()._lazy_compilation) {
                 final FunctionNode fn = (FunctionNode)fnExpr;
                 if (callExpr.getArgs().isEmpty()) {
                     final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(fn.getId());
diff --git a/src/jdk/nashorn/internal/codegen/TypeMap.java b/src/jdk/nashorn/internal/codegen/TypeMap.java
index 11efce1..a26e6b9 100644
--- a/src/jdk/nashorn/internal/codegen/TypeMap.java
+++ b/src/jdk/nashorn/internal/codegen/TypeMap.java
@@ -27,21 +27,18 @@
 
 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.
+ * A tuple containing function id, parameter types, return type and needsCallee flag.
  */
-public class TypeMap {
-    private final Map<Integer, Type[]> paramTypeMap  = new HashMap<>();
-    private final Map<Integer, Type>   returnTypeMap = new HashMap<>();
+public final class TypeMap {
+    private final int functionNodeId;
+    private final Type[] paramTypes;
+    private final Type returnType;
     private final boolean needsCallee;
 
     /**
@@ -56,9 +53,10 @@
         for (final Class<?> p : type.parameterArray()) {
             types[pos++] = Type.typeFor(p);
         }
-        paramTypeMap.put(functionNodeId, types);
-        returnTypeMap.put(functionNodeId, Type.typeFor(type.returnType()));
 
+        this.functionNodeId = functionNodeId;
+        this.paramTypes = types;
+        this.returnType = Type.typeFor(type.returnType());
         this.needsCallee = needsCallee;
     }
 
@@ -69,20 +67,14 @@
      * @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));
-        }
+        assert this.functionNodeId == 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());
+        assert this.functionNodeId == functionNode.getId();
+        final Type[] types = paramTypes;
+        MethodType mt = MethodType.methodType(returnType.getTypeClass());
         if (needsCallee) {
             mt = mt.appendParameterTypes(ScriptFunction.class);
         }
@@ -116,7 +108,8 @@
      * @return parameter type for this callsite if known
      */
     Type get(final FunctionNode functionNode, final int pos) {
-        final Type[] types = paramTypeMap.get(functionNode.getId());
+        assert this.functionNodeId == functionNode.getId();
+        final Type[] types = paramTypes;
         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];
@@ -124,13 +117,6 @@
         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("");
@@ -139,27 +125,16 @@
     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');
-        }
+        final int id = functionNodeId;
+        sb.append(prefix).append('\t');
+        sb.append("function ").append(id).append('\n');
+        sb.append(prefix).append("\t\tparamTypes=");
+        sb.append(Arrays.toString(paramTypes));
+        sb.append('\n');
+        sb.append(prefix).append("\t\treturnType=");
+        final Type ret = returnType;
+        sb.append(ret == null ? "N/A" : ret);
+        sb.append('\n');
 
         return sb.toString();
     }
diff --git a/src/jdk/nashorn/internal/codegen/WeighNodes.java b/src/jdk/nashorn/internal/codegen/WeighNodes.java
index 26660a3..494afb4 100644
--- a/src/jdk/nashorn/internal/codegen/WeighNodes.java
+++ b/src/jdk/nashorn/internal/codegen/WeighNodes.java
@@ -40,15 +40,17 @@
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.IfNode;
 import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.JumpToInlinedFinally;
 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.ObjectNode;
 import jdk.nashorn.internal.ir.PropertyNode;
 import jdk.nashorn.internal.ir.ReturnNode;
 import jdk.nashorn.internal.ir.RuntimeNode;
 import jdk.nashorn.internal.ir.SplitNode;
+import jdk.nashorn.internal.ir.Splittable;
 import jdk.nashorn.internal.ir.SwitchNode;
 import jdk.nashorn.internal.ir.ThrowNode;
 import jdk.nashorn.internal.ir.TryNode;
@@ -87,6 +89,8 @@
     static final long THROW_WEIGHT     =  2;
     static final long VAR_WEIGHT       = 40;
     static final long WITH_WEIGHT      =  8;
+    static final long OBJECT_WEIGHT    = 16;
+    static final long SETPROP_WEIGHT   =  5;
 
     /** Accumulated weight. */
     private long weight;
@@ -197,6 +201,12 @@
         return indexNode;
     }
 
+    @Override
+    public Node leaveJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+        weight += BREAK_WEIGHT;
+        return jumpToInlinedFinally;
+    }
+
     @SuppressWarnings("rawtypes")
     @Override
     public boolean enterLiteralNode(final LiteralNode literalNode) {
@@ -206,7 +216,7 @@
             final ArrayLiteralNode arrayLiteralNode = (ArrayLiteralNode)literalNode;
             final Node[]           value            = arrayLiteralNode.getValue();
             final int[]            postsets         = arrayLiteralNode.getPostsets();
-            final List<ArrayUnit>  units            = arrayLiteralNode.getUnits();
+            final List<Splittable.SplitRange>  units            = arrayLiteralNode.getSplitRanges();
 
             if (units == null) {
                 for (final int postset : postsets) {
@@ -226,6 +236,27 @@
     }
 
     @Override
+    public boolean enterObjectNode(final ObjectNode objectNode) {
+        weight += OBJECT_WEIGHT;
+        final List<PropertyNode> properties = objectNode.getElements();
+        final boolean isSpillObject = properties.size() > CodeGenerator.OBJECT_SPILL_THRESHOLD;
+
+        for (final PropertyNode property : properties) {
+            if (!LiteralNode.isConstant(property.getValue())) {
+                weight += SETPROP_WEIGHT;
+                property.getValue().accept(this);
+            } else if (!isSpillObject) {
+                // constants in spill object are set via preset spill array,
+                // but fields objects need to set constants.
+                weight += SETPROP_WEIGHT;
+            }
+
+        }
+
+        return false;
+    }
+
+    @Override
     public Node leavePropertyNode(final PropertyNode propertyNode) {
         weight += LITERAL_WEIGHT;
         return propertyNode;
diff --git a/src/jdk/nashorn/internal/codegen/types/BooleanType.java b/src/jdk/nashorn/internal/codegen/types/BooleanType.java
index 234dbdb..9cc239a 100644
--- a/src/jdk/nashorn/internal/codegen/types/BooleanType.java
+++ b/src/jdk/nashorn/internal/codegen/types/BooleanType.java
@@ -23,31 +23,6 @@
  * questions.
  */
 
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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 static jdk.internal.org.objectweb.asm.Opcodes.I2D;
diff --git a/src/jdk/nashorn/internal/codegen/types/BytecodeOps.java b/src/jdk/nashorn/internal/codegen/types/BytecodeOps.java
index 1cfb757..31e4bb6 100644
--- a/src/jdk/nashorn/internal/codegen/types/BytecodeOps.java
+++ b/src/jdk/nashorn/internal/codegen/types/BytecodeOps.java
@@ -36,7 +36,7 @@
  * The bytecode ops are coupled to a MethodVisitor from ASM for
  * byte code generation. They know nothing about our MethodGenerator,
  * which is the abstraction for working with Nashorn JS types
- * For exmaple, anything like "two or one slots" for a type, which
+ * For example, anything like "two or one slots" for a type, which
  * is represented in bytecode and ASM, is abstracted away in the
  * MethodGenerator. There you just say "dup" or "store".
  *
diff --git a/src/jdk/nashorn/internal/codegen/types/Type.java b/src/jdk/nashorn/internal/codegen/types/Type.java
index 2cf2d9b..cf53c66 100644
--- a/src/jdk/nashorn/internal/codegen/types/Type.java
+++ b/src/jdk/nashorn/internal/codegen/types/Type.java
@@ -65,6 +65,7 @@
 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.Context;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.Undefined;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
@@ -256,6 +257,9 @@
         case jdk.internal.org.objectweb.asm.Type.DOUBLE:
             return NUMBER;
         case jdk.internal.org.objectweb.asm.Type.OBJECT:
+            if (Context.isStructureClass(itype.getClassName())) {
+                return SCRIPT_OBJECT;
+            }
             try {
                 return Type.typeFor(Class.forName(itype.getClassName()));
             } catch(final ClassNotFoundException e) {
@@ -949,7 +953,7 @@
     /**
      * This is the singleton for integer arrays
      */
-    public static final ArrayType INT_ARRAY = new ArrayType(int[].class) {
+    public static final ArrayType INT_ARRAY = putInCache(new ArrayType(int[].class) {
         private static final long serialVersionUID = 1L;
 
         @Override
@@ -973,12 +977,12 @@
         public Type getElementType() {
             return INT;
         }
-    };
+    });
 
     /**
      * This is the singleton for long arrays
      */
-    public static final ArrayType LONG_ARRAY = new ArrayType(long[].class) {
+    public static final ArrayType LONG_ARRAY = putInCache(new ArrayType(long[].class) {
         private static final long serialVersionUID = 1L;
 
         @Override
@@ -1002,12 +1006,12 @@
         public Type getElementType() {
             return LONG;
         }
-    };
+    });
 
     /**
      * This is the singleton for numeric arrays
      */
-    public static final ArrayType NUMBER_ARRAY = new ArrayType(double[].class) {
+    public static final ArrayType NUMBER_ARRAY = putInCache(new ArrayType(double[].class) {
         private static final long serialVersionUID = 1L;
 
         @Override
@@ -1031,13 +1035,7 @@
         public Type getElementType() {
             return NUMBER;
         }
-    };
-
-    /** Singleton for method handle arrays used for properties etc. */
-    public static final ArrayType METHODHANDLE_ARRAY = putInCache(new ArrayType(MethodHandle[].class));
-
-    /** This is the singleton for string arrays */
-    public static final ArrayType STRING_ARRAY = putInCache(new ArrayType(String[].class));
+    });
 
     /** This is the singleton for object arrays */
     public static final ArrayType OBJECT_ARRAY = putInCache(new ArrayType(Object[].class));
diff --git a/src/jdk/nashorn/internal/ir/AccessNode.java b/src/jdk/nashorn/internal/ir/AccessNode.java
index b8b6482..315ee39 100644
--- a/src/jdk/nashorn/internal/ir/AccessNode.java
+++ b/src/jdk/nashorn/internal/ir/AccessNode.java
@@ -28,8 +28,6 @@
 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 of a property access (period operator.)
@@ -103,14 +101,6 @@
         return property;
     }
 
-    /**
-     * Return true if this node represents an index operation normally represented as {@link IndexNode}.
-     * @return true if an index access.
-     */
-    public boolean isIndex() {
-        return Token.descType(getToken()) == TokenType.LBRACKET;
-    }
-
     private AccessNode setBase(final Expression base) {
         if (this.base == base) {
             return this;
diff --git a/src/jdk/nashorn/internal/ir/BaseNode.java b/src/jdk/nashorn/internal/ir/BaseNode.java
index 35479a7..4e59753 100644
--- a/src/jdk/nashorn/internal/ir/BaseNode.java
+++ b/src/jdk/nashorn/internal/ir/BaseNode.java
@@ -27,9 +27,9 @@
 
 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.parser.TokenType;
 
 /**
  * IR base for accessing/indexing nodes.
@@ -98,7 +98,7 @@
     }
 
     @Override
-    public Type getType(final Function<Symbol, Type> localVariableTypes) {
+    public Type getType() {
         return type == null ? getMostPessimisticType() : type;
     }
 
@@ -123,6 +123,14 @@
     }
 
     /**
+     * Return true if this node represents an index operation normally represented as {@link IndexNode}.
+     * @return true if an index access.
+     */
+    public boolean isIndex() {
+        return isTokenType(TokenType.LBRACKET);
+    }
+
+    /**
      * 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/src/jdk/nashorn/internal/ir/BinaryNode.java b/src/jdk/nashorn/internal/ir/BinaryNode.java
index f625fe1..9f2efa3 100644
--- a/src/jdk/nashorn/internal/ir/BinaryNode.java
+++ b/src/jdk/nashorn/internal/ir/BinaryNode.java
@@ -31,7 +31,6 @@
 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;
@@ -57,9 +56,7 @@
     private final int programPoint;
 
     private final Type type;
-
     private transient Type cachedType;
-    private transient Object cachedTypeFunction;
 
     @Ignore
     private static final Set<TokenType> CAN_OVERFLOW =
@@ -101,7 +98,7 @@
     }
 
     /**
-     * Returns true if the node is a comparison operation.
+     * Returns true if the node is a comparison operation (either equality, inequality, or relational).
      * @return true if the node is a comparison operation.
      */
     public boolean isComparison() {
@@ -121,6 +118,22 @@
     }
 
     /**
+     * Returns true if the node is a relational operation (less than (or equals), greater than (or equals)).
+     * @return true if the node is a relational operation.
+     */
+    public boolean isRelational() {
+        switch (tokenType()) {
+        case LT:
+        case GT:
+        case LE:
+        case GE:
+            return true;
+        default:
+            return false;
+        }
+    }
+
+    /**
      * Returns true if the node is a logical operation.
      * @return true if the node is a logical operation.
      */
@@ -143,24 +156,6 @@
         }
     }
 
-    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
-     *
-     * @return Type
-     */
-    @Override
-    public Type getWidestOperationType() {
-        return getWidestOperationType(UNKNOWN_LOCALS);
-    }
-
     /**
      * Return the widest possible operand type for this operation.
      *
@@ -181,14 +176,15 @@
         }
     }
 
-    private Type getWidestOperationType(final Function<Symbol, Type> localVariableTypes) {
+    @Override
+    public Type getWidestOperationType() {
         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);
+            final Type lhsType = lhs.getType();
+            final Type rhsType = rhs.getType();
             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
@@ -238,8 +234,8 @@
         case SUB:
         case ASSIGN_MUL:
         case ASSIGN_SUB: {
-            final Type lhsType = lhs.getType(localVariableTypes);
-            final Type rhsType = rhs.getType(localVariableTypes);
+            final Type lhsType = lhs.getType();
+            final Type rhsType = rhs.getType();
             if(lhsType == Type.BOOLEAN && rhsType == Type.BOOLEAN) {
                 return Type.INT;
             }
@@ -253,20 +249,20 @@
             return Type.UNDEFINED;
         }
         case ASSIGN: {
-            return rhs.getType(localVariableTypes);
+            return rhs.getType();
         }
         case INSTANCEOF: {
             return Type.BOOLEAN;
         }
         case COMMALEFT: {
-            return lhs.getType(localVariableTypes);
+            return lhs.getType();
         }
         case COMMARIGHT: {
-            return rhs.getType(localVariableTypes);
+            return rhs.getType();
         }
         case AND:
         case OR:{
-            return Type.widestReturnType(lhs.getType(localVariableTypes), rhs.getType(localVariableTypes));
+            return Type.widestReturnType(lhs.getType(), rhs.getType());
         }
         default:
             if (isComparison()) {
@@ -316,7 +312,7 @@
 
     @Override
     public boolean isSelfModifying() {
-        return isAssignment() && tokenType() != TokenType.ASSIGN;
+        return isAssignment() && !isTokenType(TokenType.ASSIGN);
     }
 
     @Override
@@ -487,7 +483,7 @@
 
     /**
      * Set the right hand side expression for this node
-     * @param rhs new left hand side expression
+     * @param rhs new right hand side expression
      * @return a node equivalent to this one except for the requested change.
      */
     public BinaryNode setRHS(final Expression rhs) {
@@ -497,6 +493,19 @@
         return new BinaryNode(this, lhs, rhs, type, programPoint);
     }
 
+    /**
+     * Set both the left and the right hand side expression for this node
+     * @param lhs new left hand side expression
+     * @param rhs new left hand side expression
+     * @return a node equivalent to this one except for the requested change.
+     */
+    public BinaryNode setOperands(final Expression lhs, final Expression rhs) {
+        if (this.lhs == lhs && this.rhs == rhs) {
+            return this;
+        }
+        return new BinaryNode(this, lhs, rhs, type, programPoint);
+    }
+
     @Override
     public int getProgramPoint() {
         return programPoint;
@@ -520,7 +529,7 @@
         final TokenType tokenType = tokenType();
         if(tokenType == TokenType.ADD || tokenType == TokenType.ASSIGN_ADD) {
             return OPTIMISTIC_UNDECIDED_TYPE;
-        } else if (CAN_OVERFLOW.contains(tokenType())) {
+        } else if (CAN_OVERFLOW.contains(tokenType)) {
             return Type.INT;
         }
         return getMostPessimisticType();
@@ -541,24 +550,22 @@
     }
 
     @Override
-    public Type getType(final Function<Symbol, Type> localVariableTypes) {
-        if(localVariableTypes == cachedTypeFunction) {
-            return cachedType;
+    public Type getType() {
+        if (cachedType == null) {
+            cachedType = getTypeUncached();
         }
-        cachedType = getTypeUncached(localVariableTypes);
-        cachedTypeFunction = localVariableTypes;
         return cachedType;
     }
 
-    private Type getTypeUncached(final Function<Symbol, Type> localVariableTypes) {
+    private Type getTypeUncached() {
         if(type == OPTIMISTIC_UNDECIDED_TYPE) {
-            return decideType(lhs.getType(localVariableTypes), rhs.getType(localVariableTypes));
+            return decideType(lhs.getType(), rhs.getType());
         }
-        final Type widest = getWidestOperationType(localVariableTypes);
+        final Type widest = getWidestOperationType();
         if(type == null) {
             return widest;
         }
-        return Type.narrowest(widest, Type.widest(type, Type.widest(lhs.getType(localVariableTypes), rhs.getType(localVariableTypes))));
+        return Type.narrowest(widest, Type.widest(type, Type.widest(lhs.getType(), rhs.getType())));
     }
 
     private static Type decideType(final Type lhsType, final Type rhsType) {
diff --git a/src/jdk/nashorn/internal/ir/Block.java b/src/jdk/nashorn/internal/ir/Block.java
index 12e4fcd..1647a92 100644
--- a/src/jdk/nashorn/internal/ir/Block.java
+++ b/src/jdk/nashorn/internal/ir/Block.java
@@ -130,11 +130,42 @@
     }
 
     /**
-     * Clear the symbols in the block.
-     * TODO: make this immutable.
+     * Returns true if this block defines any symbols.
+     * @return true if this block defines any symbols.
      */
-    public void clearSymbols() {
-        symbols.clear();
+    public boolean hasSymbols() {
+        return !symbols.isEmpty();
+    }
+
+    /**
+     * Replaces symbols defined in this block with different symbols. Used to ensure symbol tables are
+     * immutable upon construction and have copy-on-write semantics. Note that this method only replaces the
+     * symbols in the symbol table, it does not act on any contained AST nodes that might reference the symbols.
+     * Those should be updated separately as this method is meant to be used as part of such an update pass.
+     * @param lc the current lexical context
+     * @param replacements the map of symbol replacements
+     * @return a new block with replaced symbols, or this block if none of the replacements modified the symbol
+     * table.
+     */
+    public Block replaceSymbols(final LexicalContext lc, final Map<Symbol, Symbol> replacements) {
+        if (symbols.isEmpty()) {
+            return this;
+        }
+        final LinkedHashMap<String, Symbol> newSymbols = new LinkedHashMap<>(symbols);
+        for (final Map.Entry<String, Symbol> entry: newSymbols.entrySet()) {
+            final Symbol newSymbol = replacements.get(entry.getValue());
+            assert newSymbol != null : "Missing replacement for " + entry.getKey();
+            entry.setValue(newSymbol);
+        }
+        return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, newSymbols, conversion));
+    }
+
+    /**
+     * Returns a copy of this block with a shallow copy of the symbol table.
+     * @return a copy of this block with a shallow copy of the symbol table.
+     */
+    public Block copyWithNewSymbols() {
+        return new Block(this, finish, statements, flags, new LinkedHashMap<>(symbols), conversion);
     }
 
     @Override
@@ -162,7 +193,7 @@
      * @return symbol iterator
      */
     public List<Symbol> getSymbols() {
-        return Collections.unmodifiableList(new ArrayList<>(symbols.values()));
+        return symbols.isEmpty() ? Collections.<Symbol>emptyList() : Collections.unmodifiableList(new ArrayList<>(symbols.values()));
     }
 
     /**
@@ -298,6 +329,14 @@
     }
 
     /**
+     * Returns the last statement in the block.
+     * @return the last statement in the block, or null if the block has no statements.
+     */
+    public Statement getLastStatement() {
+        return statements.isEmpty() ? null : statements.get(statements.size() - 1);
+    }
+
+    /**
      * Reset the statement list for this block
      *
      * @param lc lexical context
@@ -318,10 +357,9 @@
     /**
      * Add or overwrite an existing symbol in the block
      *
-     * @param lc     get lexical context
      * @param symbol symbol
      */
-    public void putSymbol(final LexicalContext lc, final Symbol symbol) {
+    public void putSymbol(final Symbol symbol) {
         symbols.put(symbol.getName(), symbol);
     }
 
diff --git a/src/jdk/nashorn/internal/ir/BlockLexicalContext.java b/src/jdk/nashorn/internal/ir/BlockLexicalContext.java
index 7e16b5e..1848d2a 100644
--- a/src/jdk/nashorn/internal/ir/BlockLexicalContext.java
+++ b/src/jdk/nashorn/internal/ir/BlockLexicalContext.java
@@ -34,7 +34,7 @@
  * This is a subclass of lexical context used for filling
  * blocks (and function nodes) with statements. When popping
  * a block from the lexical context, any statements that have
- * been generated in it are commited to the block. This saves
+ * been generated in it are committed to the block. This saves
  * unnecessary object mutations and lexical context replacement
  */
 public class BlockLexicalContext extends LexicalContext {
@@ -74,7 +74,7 @@
 
     @SuppressWarnings("unchecked")
     @Override
-    public <T extends LexicalContextNode> T pop(final T node) {
+    public <T extends Node> T pop(final T node) {
         T expected = node;
         if (node instanceof Block) {
             final List<Statement> newStatements = popStatements();
diff --git a/src/jdk/nashorn/internal/ir/BlockStatement.java b/src/jdk/nashorn/internal/ir/BlockStatement.java
index 6f6a1d2..3a7c810 100644
--- a/src/jdk/nashorn/internal/ir/BlockStatement.java
+++ b/src/jdk/nashorn/internal/ir/BlockStatement.java
@@ -40,6 +40,15 @@
     /**
      * Constructor
      *
+     * @param block the block to execute
+     */
+    public BlockStatement(final Block block) {
+        this(block.getFirstStatementLineNumber(), block);
+    }
+
+    /**
+     * Constructor
+     *
      * @param lineNumber line number
      * @param block the block to execute
      */
diff --git a/src/jdk/nashorn/internal/ir/BreakNode.java b/src/jdk/nashorn/internal/ir/BreakNode.java
index 4cbf4c0..3e80bcc 100644
--- a/src/jdk/nashorn/internal/ir/BreakNode.java
+++ b/src/jdk/nashorn/internal/ir/BreakNode.java
@@ -77,7 +77,7 @@
     }
 
     @Override
-    public Label getTargetLabel(final BreakableNode target) {
+    Label getTargetLabel(final BreakableNode target) {
         return target.getBreakLabel();
     }
 }
diff --git a/src/jdk/nashorn/internal/ir/CallNode.java b/src/jdk/nashorn/internal/ir/CallNode.java
index 72eab68..95a1166 100644
--- a/src/jdk/nashorn/internal/ir/CallNode.java
+++ b/src/jdk/nashorn/internal/ir/CallNode.java
@@ -30,7 +30,6 @@
 import java.io.Serializable;
 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;
@@ -154,7 +153,7 @@
     }
 
     @Override
-    public Type getType(final Function<Symbol, Type> localVariableTypes) {
+    public Type getType() {
         return optimisticType == null ? Type.OBJECT : optimisticType;
     }
 
diff --git a/src/jdk/nashorn/internal/ir/ContinueNode.java b/src/jdk/nashorn/internal/ir/ContinueNode.java
index c58531b..eb67f41 100644
--- a/src/jdk/nashorn/internal/ir/ContinueNode.java
+++ b/src/jdk/nashorn/internal/ir/ContinueNode.java
@@ -78,7 +78,7 @@
     }
 
     @Override
-    public Label getTargetLabel(final BreakableNode target) {
+    Label getTargetLabel(final BreakableNode target) {
         return ((LoopNode)target).getContinueLabel();
     }
 }
diff --git a/src/jdk/nashorn/internal/ir/Expression.java b/src/jdk/nashorn/internal/ir/Expression.java
index 7852341..e62eb73 100644
--- a/src/jdk/nashorn/internal/ir/Expression.java
+++ b/src/jdk/nashorn/internal/ir/Expression.java
@@ -25,7 +25,6 @@
 
 package jdk.nashorn.internal.ir;
 
-import java.util.function.Function;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
 
@@ -39,14 +38,7 @@
 
     static final String OPT_IDENTIFIER = "%";
 
-    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) {
+    protected Expression(final long token, final int start, final int finish) {
         super(token, start, finish);
     }
 
@@ -63,18 +55,7 @@
      *
      * @return the type of the expression.
      */
-    public final Type getType() {
-        return getType(UNKNOWN_LOCALS);
-    }
-
-    /**
-     * 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 abstract Type getType(final Function<Symbol, Type> localVariableTypes);
+    public abstract Type getType();
 
     /**
      * Returns {@code true} if this expression depends exclusively on state that is constant
diff --git a/src/jdk/nashorn/internal/ir/ForNode.java b/src/jdk/nashorn/internal/ir/ForNode.java
index ef6f11d..d244bba 100644
--- a/src/jdk/nashorn/internal/ir/ForNode.java
+++ b/src/jdk/nashorn/internal/ir/ForNode.java
@@ -43,7 +43,7 @@
     private final JoinPredecessorExpression modify;
 
     /** Iterator symbol. */
-    private Symbol iterator;
+    private final Symbol iterator;
 
     /** Is this a normal for in loop? */
     public static final int IS_FOR_IN           = 1 << 0;
@@ -70,22 +70,22 @@
         this.flags  = flags;
         this.init = null;
         this.modify = null;
+        this.iterator = null;
     }
 
     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) {
+            final Block body, final JoinPredecessorExpression modify, final int flags,
+            final boolean controlFlowEscapes, final LocalVariableConversion conversion, final Symbol iterator) {
         super(forNode, test, body, controlFlowEscapes, conversion);
         this.init   = init;
         this.modify = modify;
         this.flags  = flags;
-        // 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;
+        this.iterator = iterator;
     }
 
     @Override
     public Node ensureUniqueLabels(final LexicalContext lc) {
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
     }
 
     @Override
@@ -158,7 +158,7 @@
         if (this.init == init) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
     }
 
     /**
@@ -206,10 +206,15 @@
 
     /**
      * Assign an iterator symbol to this ForNode. Used for for in and for each constructs
+     * @param lc the current lexical context
      * @param iterator the iterator symbol
+     * @return a ForNode with the iterator set
      */
-    public void setIterator(final Symbol iterator) {
-        this.iterator = iterator;
+    public ForNode setIterator(final LexicalContext lc, final Symbol iterator) {
+        if (this.iterator == iterator) {
+            return this;
+        }
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
     }
 
     /**
@@ -230,7 +235,7 @@
         if (this.modify == modify) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
     }
 
     @Override
@@ -238,7 +243,7 @@
         if (this.test == test) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
     }
 
     @Override
@@ -251,7 +256,7 @@
         if (this.body == body) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
     }
 
     @Override
@@ -259,19 +264,19 @@
         if (this.controlFlowEscapes == controlFlowEscapes) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
     }
 
     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, conversion));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
     }
 
     @Override
     JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) {
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
     }
 
     @Override
diff --git a/src/jdk/nashorn/internal/ir/FunctionNode.java b/src/jdk/nashorn/internal/ir/FunctionNode.java
index 0806fea..02bf160 100644
--- a/src/jdk/nashorn/internal/ir/FunctionNode.java
+++ b/src/jdk/nashorn/internal/ir/FunctionNode.java
@@ -33,11 +33,8 @@
 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_VALUES;
 
 import java.util.Collections;
-import java.util.EnumSet;
 import java.util.Iterator;
 import java.util.List;
-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;
@@ -74,40 +71,6 @@
         SETTER
     }
 
-    /** Compilation states available */
-    public enum CompilationState {
-        /** compiler is ready */
-        INITIALIZED,
-        /** method has been parsed */
-        PARSED,
-        /** method has been parsed */
-        PARSE_ERROR,
-        /** constant folding pass */
-        CONSTANT_FOLDED,
-        /** method has been lowered */
-        LOWERED,
-        /** 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 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 */
-        BYTECODE_GENERATED,
-        /** method has been installed */
-        BYTECODE_INSTALLED
-    }
-
     /** Source of entity. */
     private transient final Source source;
 
@@ -145,10 +108,6 @@
     /** Method's namespace. */
     private transient final Namespace namespace;
 
-    /** Current compilation state */
-    @Ignore
-    private final EnumSet<CompilationState> compilationState;
-
     /** Number of properties of "this" object assigned in this function */
     @Ignore
     private final int thisProperties;
@@ -264,6 +223,11 @@
      */
     public static final int NEEDS_CALLEE       = 1 << 26;
 
+    /**
+     * Is the function node cached?
+     */
+    public static final int IS_CACHED = 1 << 27;
+
     /** 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 |
@@ -323,7 +287,6 @@
         this.firstToken       = firstToken;
         this.lastToken        = token;
         this.namespace        = namespace;
-        this.compilationState = EnumSet.of(CompilationState.INITIALIZED);
         this.flags            = flags;
         this.compileUnit      = null;
         this.body             = null;
@@ -340,12 +303,11 @@
         final String name,
         final Type returnType,
         final CompileUnit compileUnit,
-        final EnumSet<CompilationState> compilationState,
         final Block body,
         final List<IdentNode> parameters,
         final int thisProperties,
         final Class<?> rootClass,
-        final Source source, Namespace namespace) {
+        final Source source, final Namespace namespace) {
         super(functionNode);
 
         this.endParserState    = endParserState;
@@ -355,7 +317,6 @@
         this.returnType       = returnType;
         this.compileUnit      = compileUnit;
         this.lastToken        = lastToken;
-        this.compilationState = compilationState;
         this.body             = body;
         this.parameters       = parameters;
         this.thisProperties   = thisProperties;
@@ -455,7 +416,6 @@
             name,
             returnType,
             compileUnit,
-            compilationState,
             body,
             parameters,
             thisProperties,
@@ -531,80 +491,6 @@
     }
 
     /**
-     * Get the compilation state of this function
-     * @return the compilation state
-     */
-    public EnumSet<CompilationState> getState() {
-        return compilationState;
-    }
-
-    /**
-     * Check whether this FunctionNode has reached a give CompilationState.
-     *
-     * @param state the state to check for
-     * @return true of the node is in the given state
-     */
-    public boolean hasState(final EnumSet<CompilationState> state) {
-        return !AssertsEnabled.assertsEnabled() || compilationState.containsAll(state);
-    }
-
-    /**
-     * Add a state to the total CompilationState of this node, e.g. if
-     * FunctionNode has been lowered, the compiler will add
-     * {@code CompilationState#LOWERED} to the state vector
-     *
-     * @param lc lexical context
-     * @param state {@link CompilationState} to add
-     * @return function node or a new one if state was changed
-     */
-    public FunctionNode setState(final LexicalContext lc, final CompilationState state) {
-        if (!AssertsEnabled.assertsEnabled() || this.compilationState.contains(state)) {
-            return this;
-        }
-        final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
-        newState.add(state);
-        return setCompilationState(lc, newState);
-    }
-
-    /**
-     * Copy a compilation state from an original function to this function. Used when creating synthetic
-     * function nodes by the splitter.
-     *
-     * @param lc lexical context
-     * @param original the original function node to copy compilation state from
-     * @return function node or a new one if state was changed
-     */
-    public FunctionNode copyCompilationState(final LexicalContext lc, final FunctionNode original) {
-        final EnumSet<CompilationState> origState = original.compilationState;
-        if (!AssertsEnabled.assertsEnabled() || this.compilationState.containsAll(origState)) {
-            return this;
-        }
-        final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
-        newState.addAll(origState);
-        return setCompilationState(lc, newState);
-    }
-
-    private FunctionNode setCompilationState(final LexicalContext lc, final EnumSet<CompilationState> compilationState) {
-        return Node.replaceInLexicalContext(
-                lc,
-                this,
-                new FunctionNode(
-                        this,
-                        lastToken,
-                        endParserState,
-                        flags,
-                        name,
-                        returnType,
-                        compileUnit,
-                        compilationState,
-                        body,
-                        parameters,
-                        thisProperties,
-                        rootClass, source, namespace));
-    }
-
-
-    /**
      * Create a unique name in the namespace of this FunctionNode
      * @param base prefix for name
      * @return base if no collision exists, otherwise a name prefix with base
@@ -669,7 +555,6 @@
                         name,
                         returnType,
                         compileUnit,
-                        compilationState,
                         body,
                         parameters,
                         thisProperties,
@@ -749,7 +634,7 @@
      */
     public boolean needsCallee() {
         // NOTE: we only need isSplit() here to ensure that :scope can never drop below slot 2 for splitting array units.
-        return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasOptimisticApplyToCall();
+        return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasApplyToCallSpecialization();
     }
 
     /**
@@ -766,7 +651,7 @@
      * Return true if function contains an apply to call transform
      * @return true if this function has transformed apply to call
      */
-    public boolean hasOptimisticApplyToCall() {
+    public boolean hasApplyToCallSpecialization() {
         return getFlag(HAS_APPLY_TO_CALL_SPECIALIZATION);
     }
 
@@ -810,7 +695,6 @@
                         name,
                         returnType,
                         compileUnit,
-                        compilationState,
                         body,
                         parameters,
                         thisProperties,
@@ -906,7 +790,6 @@
                         name,
                         returnType,
                         compileUnit,
-                        compilationState,
                         body,
                         parameters,
                         thisProperties,
@@ -967,7 +850,6 @@
                         name,
                         returnType,
                         compileUnit,
-                        compilationState,
                         body,
                         parameters,
                         thisProperties,
@@ -1003,7 +885,6 @@
                         name,
                         returnType,
                         compileUnit,
-                        compilationState,
                         body,
                         parameters,
                         thisProperties,
@@ -1041,7 +922,6 @@
                         name,
                         returnType,
                         compileUnit,
-                        compilationState,
                         body,
                         parameters,
                         thisProperties,
@@ -1078,6 +958,14 @@
     }
 
     /**
+     * Return the number of parameters to this function
+     * @return the number of parameters
+     */
+    public int getNumOfParams() {
+        return parameters.size();
+    }
+
+    /**
      * 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.
@@ -1109,7 +997,6 @@
                         name,
                         returnType,
                         compileUnit,
-                        compilationState,
                         body,
                         parameters,
                         thisProperties,
@@ -1142,8 +1029,17 @@
         return getFlag(USES_SELF_SYMBOL);
     }
 
+    /**
+     * Returns true if this is a named function expression (that is, it isn't a declared function, it isn't an
+     * anonymous function expression, and it isn't a program).
+     * @return true if this is a named function expression
+     */
+    public boolean isNamedFunctionExpression() {
+        return !getFlag(IS_PROGRAM | IS_ANONYMOUS | IS_DECLARED);
+    }
+
     @Override
-    public Type getType(final Function<Symbol, Type> localVariableTypes) {
+    public Type getType() {
         return FUNCTION_TYPE;
     }
 
@@ -1188,7 +1084,6 @@
                 name,
                 type,
                 compileUnit,
-                compilationState,
                 body,
                 parameters,
                 thisProperties,
@@ -1205,6 +1100,24 @@
     }
 
     /**
+     * Returns true if this function node has been cached.
+     * @return true if this function node has been cached.
+     */
+    public boolean isCached() {
+        return getFlag(IS_CACHED);
+    }
+
+    /**
+     * Mark this function node as having been cached.
+     * @param lc the current lexical context
+     * @return a function node equivalent to this one, with the flag set.
+     */
+    public FunctionNode setCached(final LexicalContext lc) {
+        return setFlag(lc, IS_CACHED);
+    }
+
+
+    /**
      * Get the compile unit used to compile this function
      * @see Compiler
      * @return the compile unit
@@ -1236,7 +1149,6 @@
                         name,
                         returnType,
                         compileUnit,
-                        compilationState,
                         body,
                         parameters,
                         thisProperties,
@@ -1292,7 +1204,6 @@
                         name,
                         returnType,
                         compileUnit,
-                        compilationState,
                         body,
                         parameters,
                         thisProperties,
diff --git a/src/jdk/nashorn/internal/ir/GetSplitState.java b/src/jdk/nashorn/internal/ir/GetSplitState.java
index bf4a4c0..29c11b4 100644
--- a/src/jdk/nashorn/internal/ir/GetSplitState.java
+++ b/src/jdk/nashorn/internal/ir/GetSplitState.java
@@ -25,7 +25,6 @@
 
 package jdk.nashorn.internal.ir;
 
-import java.util.function.Function;
 import jdk.nashorn.internal.codegen.CompilerConstants;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -47,7 +46,7 @@
     }
 
     @Override
-    public Type getType(final Function<Symbol, Type> localVariableTypes) {
+    public Type getType() {
         return Type.INT;
     }
 
diff --git a/src/jdk/nashorn/internal/ir/IdentNode.java b/src/jdk/nashorn/internal/ir/IdentNode.java
index 7059734..4570181 100644
--- a/src/jdk/nashorn/internal/ir/IdentNode.java
+++ b/src/jdk/nashorn/internal/ir/IdentNode.java
@@ -30,7 +30,6 @@
 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;
@@ -118,14 +117,13 @@
     }
 
     @Override
-    public Type getType(final Function<Symbol, Type> localVariableTypes) {
+    public Type getType() {
         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;
+        return Type.UNDEFINED;
     }
 
     /**
diff --git a/src/jdk/nashorn/internal/ir/JoinPredecessorExpression.java b/src/jdk/nashorn/internal/ir/JoinPredecessorExpression.java
index cfb0086..7f0d990 100644
--- a/src/jdk/nashorn/internal/ir/JoinPredecessorExpression.java
+++ b/src/jdk/nashorn/internal/ir/JoinPredecessorExpression.java
@@ -25,7 +25,6 @@
 
 package jdk.nashorn.internal.ir;
 
-import java.util.function.Function;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 
@@ -71,8 +70,8 @@
     }
 
     @Override
-    public Type getType(final Function<Symbol, Type> localVariableTypes) {
-        return expression.getType(localVariableTypes);
+    public Type getType() {
+        return expression.getType();
     }
 
     @Override
diff --git a/src/jdk/nashorn/internal/ir/JumpStatement.java b/src/jdk/nashorn/internal/ir/JumpStatement.java
index 0770717..628bc77 100644
--- a/src/jdk/nashorn/internal/ir/JumpStatement.java
+++ b/src/jdk/nashorn/internal/ir/JumpStatement.java
@@ -101,7 +101,26 @@
      * @throws ClassCastException if invoked on the kind of breakable node that this jump statement is not prepared to
      * handle.
      */
-    public abstract Label getTargetLabel(final BreakableNode target);
+    abstract Label getTargetLabel(final BreakableNode target);
+
+    /**
+     * Returns the label this jump statement targets.
+     * @param lc the lexical context
+     * @return the label this jump statement targets.
+     */
+    public Label getTargetLabel(final LexicalContext lc) {
+        return getTargetLabel(getTarget(lc));
+    }
+
+    /**
+     * Returns the limit node for popping scopes when this jump statement is effected.
+     * @param lc the current lexical context
+     * @return the limit node for popping scopes when this jump statement is effected.
+     */
+    public LexicalContextNode getPopScopeLimit(final LexicalContext lc) {
+        // In most cases (break and continue) this is equal to the target.
+        return getTarget(lc);
+    }
 
     @Override
     public JumpStatement setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
diff --git a/src/jdk/nashorn/internal/ir/JumpToInlinedFinally.java b/src/jdk/nashorn/internal/ir/JumpToInlinedFinally.java
new file mode 100644
index 0000000..bba0d99
--- /dev/null
+++ b/src/jdk/nashorn/internal/ir/JumpToInlinedFinally.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.Objects;
+import jdk.nashorn.internal.codegen.Label;
+import jdk.nashorn.internal.ir.annotations.Immutable;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+
+/**
+ * IR representation for synthetic jump into an inlined finally statement.
+ */
+@Immutable
+public final class JumpToInlinedFinally extends JumpStatement {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Constructor
+     *
+     * @param labelName  label name for inlined finally block
+     */
+    public JumpToInlinedFinally(final String labelName) {
+        super(NO_LINE_NUMBER, NO_TOKEN, NO_FINISH, Objects.requireNonNull(labelName));
+    }
+
+    private JumpToInlinedFinally(final JumpToInlinedFinally breakNode, final LocalVariableConversion conversion) {
+        super(breakNode, conversion);
+    }
+
+    @Override
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+        if (visitor.enterJumpToInlinedFinally(this)) {
+            return visitor.leaveJumpToInlinedFinally(this);
+        }
+
+        return this;
+    }
+
+    @Override
+    JumpStatement createNewJumpStatement(final LocalVariableConversion conversion) {
+        return new JumpToInlinedFinally(this, conversion);
+    }
+
+    @Override
+    String getStatementName() {
+        return ":jumpToInlinedFinally";
+    }
+
+    @Override
+    public Block getTarget(final LexicalContext lc) {
+        return lc.getInlinedFinally(getLabelName());
+    }
+
+    @Override
+    public TryNode getPopScopeLimit(final LexicalContext lc) {
+        // Returns the try node to which this jump's target belongs. This will make scope popping also pop the scope
+        // for the body of the try block, if it needs scope.
+        return lc.getTryNodeForInlinedFinally(getLabelName());
+    }
+
+    @Override
+    Label getTargetLabel(final BreakableNode target) {
+        assert target != null;
+        // We're jumping to the entry of the inlined finally block
+        return ((Block)target).getEntryLabel();
+    }
+}
diff --git a/src/jdk/nashorn/internal/ir/LexicalContext.java b/src/jdk/nashorn/internal/ir/LexicalContext.java
index 487d6ae..a559da9 100644
--- a/src/jdk/nashorn/internal/ir/LexicalContext.java
+++ b/src/jdk/nashorn/internal/ir/LexicalContext.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,11 +31,13 @@
 import jdk.nashorn.internal.runtime.Source;
 
 /**
- * A class that tracks the current lexical context of node visitation as a stack of {@link Block} nodes. Has special
- * methods to retrieve useful subsets of the context.
+ * A class that tracks the current lexical context of node visitation as a stack
+ * of {@link Block} nodes. Has special methods to retrieve useful subsets of the
+ * context.
  *
- * This is implemented with a primitive array and a stack pointer, because it really makes a difference
- * performance wise. None of the collection classes were optimal
+ * This is implemented with a primitive array and a stack pointer, because it
+ * really makes a difference performance-wise. None of the collection classes
+ * were optimal.
  */
 public class LexicalContext {
     private LexicalContextNode[] stack;
@@ -79,6 +81,7 @@
      * {@link Block#NEEDS_SCOPE} because it atomically also sets the
      * {@link FunctionNode#HAS_SCOPE_BLOCK} flag on the block's containing
      * function.
+     *
      * @param block the block that needs to be marked as creating a scope.
      */
     public void setBlockNeedsScope(final Block block) {
@@ -97,8 +100,10 @@
     }
 
     /**
-     * Get the flags for a lexical context node on the stack
+     * Get the flags for a lexical context node on the stack.
+     *
      * @param node node
+     *
      * @return the flags for the node
      */
     public int getFlags(final LexicalContextNode node) {
@@ -112,8 +117,10 @@
 
     /**
      * Get the function body of a function node on the lexical context
-     * stack. This will trigger an assertion if node isn't present
+     * stack. This will trigger an assertion if node isn't present.
+     *
      * @param functionNode function node
+     *
      * @return body of function node
      */
     public Block getFunctionBody(final FunctionNode functionNode) {
@@ -126,15 +133,16 @@
     }
 
     /**
-     * Return all nodes in the LexicalContext
-     * @return all nodes
+     * @return all nodes in the LexicalContext.
      */
     public Iterator<LexicalContextNode> getAllNodes() {
         return new NodeIterator<>(LexicalContextNode.class);
     }
 
     /**
-     * Returns the outermost function in this context. It is either the program, or a lazily compiled function.
+     * Returns the outermost function in this context. It is either the program,
+     * or a lazily compiled function.
+     *
      * @return the outermost function in this context.
      */
     public FunctionNode getOutermostFunction() {
@@ -142,8 +150,12 @@
     }
 
     /**
-     * Pushes a new block on top of the context, making it the innermost open block.
+     * Pushes a new block on top of the context, making it the innermost open
+     * block.
+     *
+     * @param <T> the type of the new node
      * @param node the new node
+     *
      * @return the node that was pushed
      */
     public <T extends LexicalContextNode> T push(final T node) {
@@ -168,29 +180,32 @@
 
     /**
      * Is the context empty?
-     * @return true if empty
+     *
+     * @return {@code true} if empty
      */
     public boolean isEmpty() {
         return sp == 0;
     }
 
     /**
-     * The depth of the lexical context
-     * @return depth
+     * @return the depth of the lexical context.
      */
     public int size() {
         return sp;
     }
 
     /**
-     * Pops the innermost block off the context and all nodes that has been contributed
-     * since it was put there
+     * Pops the innermost block off the context and all nodes that has been
+     * contributed since it was put there.
      *
-     * @param node the node expected to be popped, used to detect unbalanced pushes/pops
+     * @param <T> the type of the node to be popped
+     * @param node the node expected to be popped, used to detect unbalanced
+     *        pushes/pops
+     *
      * @return the node that was popped
      */
     @SuppressWarnings("unchecked")
-    public <T extends LexicalContextNode> T pop(final T node) {
+    public <T extends Node> T pop(final T node) {
         --sp;
         final LexicalContextNode popped = stack[sp];
         stack[sp] = null;
@@ -202,11 +217,17 @@
     }
 
     /**
-     * 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.
+     * 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(Node)} 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 <T> the type of the node to apply the flags to.
+     * @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) {
@@ -215,7 +236,8 @@
     }
 
     /**
-     * Return the top element in the context
+     * Return the top element in the context.
+     *
      * @return the node that was pushed last
      */
     public LexicalContextNode peek() {
@@ -223,9 +245,11 @@
     }
 
     /**
-     * Check if a node is in the lexical context
+     * Check if a node is in the lexical context.
+     *
      * @param node node to check for
-     * @return true if in the context
+     *
+     * @return {@code true} if in the context
      */
     public boolean contains(final LexicalContextNode node) {
         for (int i = 0; i < sp; i++) {
@@ -242,6 +266,7 @@
      *
      * @param oldNode old node
      * @param newNode new node
+     *
      * @return the new node
      */
     public LexicalContextNode replace(final LexicalContextNode oldNode, final LexicalContextNode newNode) {
@@ -256,7 +281,9 @@
     }
 
     /**
-     * Returns an iterator over all blocks in the context, with the top block (innermost lexical context) first.
+     * Returns an iterator over all blocks in the context, with the top block
+     * (innermost lexical context) first.
+     *
      * @return an iterator over all blocks in the context.
      */
     public Iterator<Block> getBlocks() {
@@ -264,7 +291,9 @@
     }
 
     /**
-     * Returns an iterator over all functions in the context, with the top (innermost open) function first.
+     * Returns an iterator over all functions in the context, with the top
+     * (innermost open) function first.
+     *
      * @return an iterator over all functions in the context.
      */
     public Iterator<FunctionNode> getFunctions() {
@@ -273,6 +302,7 @@
 
     /**
      * Get the parent block for the current lexical context block
+     *
      * @return parent block
      */
     public Block getParentBlock() {
@@ -283,7 +313,9 @@
 
     /**
      * Gets the label node of the current block.
-     * @return the label node of the current block, if it is labeled. Otherwise returns null.
+     *
+     * @return the label node of the current block, if it is labeled. Otherwise
+     *         returns {@code null}.
      */
     public LabelNode getCurrentBlockLabelNode() {
         assert stack[sp - 1] instanceof Block;
@@ -294,21 +326,12 @@
         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.
+     * 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.
      */
     public Iterator<Block> getAncestorBlocks(final Block block) {
@@ -323,8 +346,11 @@
     }
 
     /**
-     * Returns an iterator over a block and all its ancestors blocks, with the block first.
+     * Returns an iterator over a block and all its ancestors blocks, with the
+     * block first.
+     *
      * @param block the block that is the starting point of the iteration.
+     *
      * @return an iterator over a block and all its ancestors.
      */
     public Iterator<Block> getBlocks(final Block block) {
@@ -352,7 +378,9 @@
 
     /**
      * Get the function for this block.
+     *
      * @param block block for which to get function
+     *
      * @return function for block
      */
     public FunctionNode getFunction(final Block block) {
@@ -373,7 +401,6 @@
     }
 
     /**
-     * Returns the innermost block in the context.
      * @return the innermost block in the context.
      */
     public Block getCurrentBlock() {
@@ -381,7 +408,6 @@
     }
 
     /**
-     * Returns the innermost function in the context.
      * @return the innermost function in the context.
      */
     public FunctionNode getCurrentFunction() {
@@ -394,9 +420,12 @@
     }
 
     /**
-     * Get the block in which a symbol is defined
+     * Get the block in which a symbol is defined.
+     *
      * @param symbol symbol
-     * @return block in which the symbol is defined, assert if no such block in context
+     *
+     * @return block in which the symbol is defined, assert if no such block in
+     *         context.
      */
     public Block getDefiningBlock(final Symbol symbol) {
         final String name = symbol.getName();
@@ -410,9 +439,12 @@
     }
 
     /**
-     * Get the function in which a symbol is defined
+     * Get the function in which a symbol is defined.
+     *
      * @param symbol symbol
-     * @return function node in which this symbol is defined, assert if no such symbol exists in context
+     *
+     * @return function node in which this symbol is defined, assert if no such
+     *         symbol exists in context.
      */
     public FunctionNode getDefiningFunction(final Symbol symbol) {
         final String name = symbol.getName();
@@ -433,7 +465,8 @@
 
     /**
      * Is the topmost lexical context element a function body?
-     * @return true if function body
+     *
+     * @return {@code true} if function body.
      */
     public boolean isFunctionBody() {
         return getParentBlock() == null;
@@ -441,16 +474,20 @@
 
     /**
      * Is the topmost lexical context element body of a SplitNode?
-     * @return true if it's the body of a split node.
+     *
+     * @return {@code true} if it's the body of a split node.
      */
     public boolean isSplitBody() {
         return sp >= 2 && stack[sp - 1] instanceof Block && stack[sp - 2] instanceof SplitNode;
     }
 
     /**
-     * Get the parent function for a function in the lexical context
+     * 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)
+     *
+     * @return parent function of functionNode or {@code null} if none (e.g., if
+     *         functionNode is the program).
      */
     public FunctionNode getParentFunction(final FunctionNode functionNode) {
         final Iterator<FunctionNode> iter = new NodeIterator<>(FunctionNode.class);
@@ -465,12 +502,16 @@
     }
 
     /**
-     * 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
+     * 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;
@@ -500,16 +541,17 @@
     }
 
     /**
-     * Check whether the lexical context is currently inside a loop
-     * @return true if inside a loop
+     * Check whether the lexical context is currently inside a loop.
+     *
+     * @return {@code true} if inside a loop
      */
     public boolean inLoop() {
         return getCurrentLoop() != null;
     }
 
     /**
-     * Returns the loop header of the current loop, or null if not inside a loop
-     * @return loop header
+     * @return the loop header of the current loop, or {@code null} if not
+     *         inside a loop.
      */
     public LoopNode getCurrentLoop() {
         final Iterator<LoopNode> iter = new NodeIterator<>(LoopNode.class, getCurrentFunction());
@@ -518,9 +560,12 @@
 
     /**
      * Find the breakable node corresponding to this 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
+     *
+     * @param labelName name of the label to search for. If {@code 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 String labelName) {
         if (labelName != null) {
@@ -544,9 +589,12 @@
 
     /**
      * Find the continue target node corresponding to this 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
+     *
+     * @param labelName label name to search for. If {@code 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 String labelName) {
         if (labelName != null) {
@@ -565,9 +613,45 @@
     }
 
     /**
-     * Check the lexical context for a given label node by name
-     * @param name name of the label
-     * @return LabelNode if found, null otherwise
+     * Find the inlined finally block node corresponding to this label.
+     *
+     * @param labelName label name to search for. Must not be {@code null}.
+     *
+     * @return closest inlined finally block with the given label.
+     */
+    public Block getInlinedFinally(final String labelName) {
+        for (final NodeIterator<TryNode> iter = new NodeIterator<>(TryNode.class); iter.hasNext(); ) {
+            final Block inlinedFinally = iter.next().getInlinedFinally(labelName);
+            if (inlinedFinally != null) {
+                return inlinedFinally;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Find the try node for an inlined finally block corresponding to this label.
+     *
+     * @param labelName label name to search for. Must not be {@code null}.
+     *
+     * @return the try node to which the labelled inlined finally block belongs.
+     */
+    public TryNode getTryNodeForInlinedFinally(final String labelName) {
+        for (final NodeIterator<TryNode> iter = new NodeIterator<>(TryNode.class); iter.hasNext(); ) {
+            final TryNode tryNode = iter.next();
+            if (tryNode.getInlinedFinally(labelName) != null) {
+                return tryNode;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Check the lexical context for a given label node by name.
+     *
+     * @param name name of the label.
+     *
+     * @return LabelNode if found, {@code null} otherwise.
      */
     public LabelNode findLabel(final String name) {
         for (final Iterator<LabelNode> iter = new NodeIterator<>(LabelNode.class, getCurrentFunction()); iter.hasNext(); ) {
@@ -580,10 +664,13 @@
     }
 
     /**
-     * Checks whether a given target is a jump destination that lies outside a given split node
-     * @param splitNode the split node
-     * @param target the target node
-     * @return true if target resides outside the split node
+     * Checks whether a given target is a jump destination that lies outside a
+     * given split node.
+     *
+     * @param splitNode the split node.
+     * @param target the target node.
+     *
+     * @return {@code true} if target resides outside the split node.
      */
     public boolean isExternalTarget(final SplitNode splitNode, final BreakableNode target) {
         for (int i = sp; i-- > 0;) {
@@ -592,14 +679,22 @@
                 return true;
             } else if (next == target) {
                 return false;
+            } else if (next instanceof TryNode) {
+                for(final Block inlinedFinally: ((TryNode)next).getInlinedFinallies()) {
+                    if (TryNode.getLabelledInlinedFinallyBlock(inlinedFinally) == target) {
+                        return false;
+                    }
+                }
             }
         }
         throw new AssertionError(target + " was expected in lexical context " + LexicalContext.this + " but wasn't");
     }
 
     /**
-     * Checks whether the current context is inside a switch statement without explicit blocks (curly braces).
-     * @return true if in unprotected switch statement
+     * Checks whether the current context is inside a switch statement without
+     * explicit blocks (curly braces).
+     *
+     * @return {@code true} if in unprotected switch statement.
      */
     public boolean inUnprotectedSwitchContext() {
         for (int i = sp; i > 0; i--) {
diff --git a/src/jdk/nashorn/internal/ir/LexicalContextNode.java b/src/jdk/nashorn/internal/ir/LexicalContextNode.java
index b53d9f6..5054b01 100644
--- a/src/jdk/nashorn/internal/ir/LexicalContextNode.java
+++ b/src/jdk/nashorn/internal/ir/LexicalContextNode.java
@@ -54,8 +54,8 @@
         static Node accept(final LexicalContextNode node, final NodeVisitor<? extends LexicalContext> visitor) {
             final LexicalContext lc = visitor.getLexicalContext();
             lc.push(node);
-            final LexicalContextNode newNode = (LexicalContextNode)node.accept(lc, visitor);
-            return (Node)lc.pop(newNode);
+            final Node newNode = node.accept(lc, visitor);
+            return lc.pop(newNode);
         }
     }
 }
diff --git a/src/jdk/nashorn/internal/ir/LiteralNode.java b/src/jdk/nashorn/internal/ir/LiteralNode.java
index 6aee20c..1f77570 100644
--- a/src/jdk/nashorn/internal/ir/LiteralNode.java
+++ b/src/jdk/nashorn/internal/ir/LiteralNode.java
@@ -25,12 +25,9 @@
 
 package jdk.nashorn.internal.ir;
 
-import java.io.Serializable;
 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;
 import jdk.nashorn.internal.ir.annotations.Immutable;
@@ -109,7 +106,7 @@
     }
 
     @Override
-    public Type getType(final Function<Symbol, Type> localVariableTypes) {
+    public Type getType() {
         return Type.typeFor(value.getClass());
     }
 
@@ -164,16 +161,6 @@
     }
 
     /**
-     * Get the array value of the node
-     *
-     * @return the array value
-     */
-    public Node[] getArray() {
-        assert false : "not an array node";
-        return null;
-    }
-
-    /**
      * Fetch String value of node.
      *
      * @return String value of node.
@@ -325,7 +312,7 @@
         }
 
         @Override
-        public Type getType(final Function<Symbol, Type> localVariableTypes) {
+        public Type getType() {
             return Type.BOOLEAN;
         }
 
@@ -389,7 +376,7 @@
         }
 
         @Override
-        public Type getType(final Function<Symbol, Type> localVariableTypes) {
+        public Type getType() {
             return type;
         }
 
@@ -441,7 +428,7 @@
      *
      * @param token   token
      * @param finish  finish
-     * @param value   undefined value, passed only for polymorphisism discrimination
+     * @param value   undefined value, passed only for polymorphism discrimination
      *
      * @return the new literal node
      */
@@ -519,7 +506,7 @@
         }
 
         @Override
-        public Type getType(final Function<Symbol, Type> localVariableTypes) {
+        public Type getType() {
             return Type.OBJECT;
         }
 
@@ -572,6 +559,15 @@
         return POSTSET_MARKER;
     }
 
+    /**
+     * Test whether {@code object} represents a constant value.
+     * @param object a node or value object
+     * @return true if object is a constant value
+     */
+    public static boolean isConstant(final Object object) {
+        return objectAsConstant(object) != POSTSET_MARKER;
+    }
+
     private static final class NullLiteralNode extends PrimitiveLiteralNode<Object> {
         private static final long serialVersionUID = 1L;
 
@@ -589,7 +585,7 @@
         }
 
         @Override
-        public Type getType(final Function<Symbol, Type> localVariableTypes) {
+        public Type getType() {
             return Type.OBJECT;
         }
 
@@ -603,7 +599,7 @@
      * Array literal node class.
      */
     @Immutable
-    public static final class ArrayLiteralNode extends LiteralNode<Expression[]> implements LexicalContextNode {
+    public static final class ArrayLiteralNode extends LiteralNode<Expression[]> implements LexicalContextNode, Splittable {
         private static final long serialVersionUID = 1L;
 
         /** Array element type. */
@@ -615,59 +611,8 @@
         /** Indices of array elements requiring computed post sets. */
         private final int[] postsets;
 
-        /** 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 final class ArrayUnit implements CompileUnitHolder, Serializable {
-            private static final long serialVersionUID = 1L;
-
-            /** Compile unit associated with the postsets range. */
-            private final CompileUnit compileUnit;
-
-            /** postsets range associated with the unit (hi not inclusive). */
-            private final int lo, hi;
-
-            /**
-             * Constructor
-             * @param compileUnit compile unit
-             * @param lo lowest array index in unit
-             * @param hi highest array index in unit + 1
-             */
-            public ArrayUnit(final CompileUnit compileUnit, final int lo, final int hi) {
-                this.compileUnit = compileUnit;
-                this.lo   = lo;
-                this.hi   = hi;
-            }
-
-            /**
-             * Get the high index position of the ArrayUnit (non inclusive)
-             * @return high index position
-             */
-            public int getHi() {
-                return hi;
-            }
-
-            /**
-             * Get the low index position of the ArrayUnit (inclusive)
-             * @return low index position
-             */
-            public int getLo() {
-                return lo;
-            }
-
-            /**
-             * The array compile unit
-             * @return array compile unit
-             */
-            @Override
-            public CompileUnit getCompileUnit() {
-                return compileUnit;
-            }
-        }
+        /** Ranges for splitting up large literals in code generation */
+        private final List<Splittable.SplitRange> splitRanges;
 
         private static final class ArrayLiteralInitializer {
 
@@ -675,7 +620,7 @@
                 final Type elementType = computeElementType(node.value);
                 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);
+                return new ArrayLiteralNode(node, node.value, elementType, postsets, presets, node.splitRanges);
             }
 
             private static Type computeElementType(final Expression[] value) {
@@ -708,7 +653,7 @@
 
                 for (int i = 0; i < value.length; i++) {
                     final Expression element = value[i];
-                    if (element == null || objectAsConstant(element) == POSTSET_MARKER) {
+                    if (element == null || !isConstant(element)) {
                         computed[nComputed++] = i;
                     }
                 }
@@ -825,24 +770,28 @@
             this.elementType = Type.UNKNOWN;
             this.presets     = null;
             this.postsets    = null;
-            this.units       = null;
+            this.splitRanges = null;
         }
 
         /**
          * Copy constructor
          * @param node source array literal node
          */
-        private ArrayLiteralNode(final ArrayLiteralNode node, final Expression[] value, final Type elementType, final int[] postsets, final Object presets, final List<ArrayUnit> units) {
+        private ArrayLiteralNode(final ArrayLiteralNode node, final Expression[] value, final Type elementType, final int[] postsets, final Object presets, final List<Splittable.SplitRange> splitRanges) {
             super(node, value);
             this.elementType = elementType;
             this.postsets    = postsets;
             this.presets     = presets;
-            this.units       = units;
+            this.splitRanges = splitRanges;
         }
 
-        @Override
-        public Node[] getArray() {
-            return value;
+        /**
+         * Returns a list of array element expressions. Note that empty array elements manifest themselves as
+         * null.
+         * @return a list of array element expressions.
+         */
+        public List<Expression> getElementExpressions() {
+            return Collections.unmodifiableList(Arrays.asList(value));
         }
 
         /**
@@ -879,7 +828,7 @@
         }
 
         @Override
-        public Type getType(final Function<Symbol, Type> localVariableTypes) {
+        public Type getType() {
             return Type.typeFor(NativeArray.class);
         }
 
@@ -924,26 +873,27 @@
         }
 
         /**
-         * Get the array units that make up this ArrayLiteral
-         * @see ArrayUnit
-         * @return list of array units
+         * Get the split ranges for this ArrayLiteral, or null if this array does not have to be split.
+         * @see Splittable.SplitRange
+         * @return list of split ranges
          */
-        public List<ArrayUnit> getUnits() {
-            return units == null ? null : Collections.unmodifiableList(units);
+        @Override
+        public List<Splittable.SplitRange> getSplitRanges() {
+            return splitRanges == null ? null : Collections.unmodifiableList(splitRanges);
         }
 
         /**
-         * Set the ArrayUnits that make up this ArrayLiteral
+         * Set the SplitRanges that make up this ArrayLiteral
          * @param lc lexical context
-         * @see ArrayUnit
-         * @param units list of array units
-         * @return new or changed arrayliteralnode
+         * @see Splittable.SplitRange
+         * @param splitRanges list of split ranges
+         * @return new or changed node
          */
-        public ArrayLiteralNode setUnits(final LexicalContext lc, final List<ArrayUnit> units) {
-            if (this.units == units) {
+        public ArrayLiteralNode setSplitRanges(final LexicalContext lc, final List<Splittable.SplitRange> splitRanges) {
+            if (this.splitRanges == splitRanges) {
                 return this;
             }
-            return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, units));
+            return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, splitRanges));
         }
 
         @Override
@@ -965,7 +915,7 @@
             if (this.value == value) {
                 return this;
             }
-            return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, units));
+            return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, splitRanges));
         }
 
         private ArrayLiteralNode setValue(final LexicalContext lc, final List<Expression> value) {
diff --git a/src/jdk/nashorn/internal/ir/Node.java b/src/jdk/nashorn/internal/ir/Node.java
index d6c5765..7762a1f 100644
--- a/src/jdk/nashorn/internal/ir/Node.java
+++ b/src/jdk/nashorn/internal/ir/Node.java
@@ -129,9 +129,17 @@
     public abstract Node accept(NodeVisitor<? extends LexicalContext> visitor);
 
     @Override
-    public String toString() {
+    public final String toString() {
+        return toString(true);
+    }
+
+    /*
+     * Return String representation of this Node.
+     * @param includeTypeInfo include type information or not
+     */
+    public final String toString(final boolean includeTypeInfo) {
         final StringBuilder sb = new StringBuilder();
-        toString(sb);
+        toString(sb, includeTypeInfo);
         return sb.toString();
     }
 
@@ -220,26 +228,28 @@
     }
 
     /**
-     * Return token tokenType from a token descriptor.
+     * Returns this node's token's type. If you want to check for the node having a specific token type,
+     * consider using {@link #isTokenType(TokenType)} instead.
      *
-     * @return Type of token.
+     * @return type of token.
      */
     public TokenType tokenType() {
         return Token.descType(token);
     }
 
     /**
-     * Test token tokenType.
+     * Tests if this node has the specific token type.
      *
-     * @param type a type to check this token against
+     * @param type a token type to check this node's token type against
      * @return true if token types match.
      */
     public boolean isTokenType(final TokenType type) {
-        return Token.descType(token) == type;
+        return tokenType() == type;
     }
 
     /**
-     * Get the token for this location
+     * Get the token for this node. If you want to retrieve the token's type, consider using
+     * {@link #tokenType()} or {@link #isTokenType(TokenType)} instead.
      * @return the token
      */
     public long getToken() {
diff --git a/src/jdk/nashorn/internal/ir/ObjectNode.java b/src/jdk/nashorn/internal/ir/ObjectNode.java
index d5bd78b..81e333c 100644
--- a/src/jdk/nashorn/internal/ir/ObjectNode.java
+++ b/src/jdk/nashorn/internal/ir/ObjectNode.java
@@ -27,7 +27,7 @@
 
 import java.util.Collections;
 import java.util.List;
-import java.util.function.Function;
+import java.util.RandomAccess;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -36,12 +36,15 @@
  * IR representation of an object literal.
  */
 @Immutable
-public final class ObjectNode extends Expression {
+public final class ObjectNode extends Expression implements LexicalContextNode, Splittable {
     private static final long serialVersionUID = 1L;
 
     /** Literal elements. */
     private final List<PropertyNode> elements;
 
+    /** Ranges for splitting large literals over multiple compile units in codegen. */
+    private final List<Splittable.SplitRange> splitRanges;
+
     /**
      * Constructor
      *
@@ -52,24 +55,32 @@
     public ObjectNode(final long token, final int finish, final List<PropertyNode> elements) {
         super(token, finish);
         this.elements = elements;
+        this.splitRanges = null;
+        assert elements instanceof RandomAccess : "Splitting requires random access lists";
     }
 
-    private ObjectNode(final ObjectNode objectNode, final List<PropertyNode> elements) {
+    private ObjectNode(final ObjectNode objectNode, final List<PropertyNode> elements,
+                       final List<Splittable.SplitRange> splitRanges ) {
         super(objectNode);
         this.elements = elements;
+        this.splitRanges = splitRanges;
     }
 
     @Override
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
-        if (visitor.enterObjectNode(this)) {
-            return visitor.leaveObjectNode(setElements(Node.accept(visitor, elements)));
-        }
+        return Acceptor.accept(this, visitor);
+    }
 
+    @Override
+    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
+        if (visitor.enterObjectNode(this)) {
+            return visitor.leaveObjectNode(setElements(lc, Node.accept(visitor, elements)));
+        }
         return this;
     }
 
     @Override
-    public Type getType(final Function<Symbol, Type> localVariableTypes) {
+    public Type getType() {
         return Type.OBJECT;
     }
 
@@ -103,10 +114,35 @@
         return Collections.unmodifiableList(elements);
     }
 
-    private ObjectNode setElements(final List<PropertyNode> elements) {
+    private ObjectNode setElements(final LexicalContext lc, final List<PropertyNode> elements) {
         if (this.elements == elements) {
             return this;
         }
-        return new ObjectNode(this, elements);
+        return Node.replaceInLexicalContext(lc, this, new ObjectNode(this, elements, this.splitRanges));
     }
+
+    /**
+     * Set the split ranges for this ObjectNode
+     * @see Splittable.SplitRange
+     * @param lc the lexical context
+     * @param splitRanges list of split ranges
+     * @return new or changed object node
+     */
+    public ObjectNode setSplitRanges(final LexicalContext lc, final List<Splittable.SplitRange> splitRanges) {
+        if (this.splitRanges == splitRanges) {
+            return this;
+        }
+        return Node.replaceInLexicalContext(lc, this, new ObjectNode(this, elements, splitRanges));
+    }
+
+    /**
+     * Get the split ranges for this ObjectNode, or null if the object is not split.
+     * @see Splittable.SplitRange
+     * @return list of split ranges
+     */
+    @Override
+    public List<Splittable.SplitRange> getSplitRanges() {
+        return splitRanges == null ? null : Collections.unmodifiableList(splitRanges);
+    }
+
 }
diff --git a/src/jdk/nashorn/internal/ir/OptimisticLexicalContext.java b/src/jdk/nashorn/internal/ir/OptimisticLexicalContext.java
index 9d97a43..18f68fe 100644
--- a/src/jdk/nashorn/internal/ir/OptimisticLexicalContext.java
+++ b/src/jdk/nashorn/internal/ir/OptimisticLexicalContext.java
@@ -115,7 +115,7 @@
     }
 
     @Override
-    public <T extends LexicalContextNode> T pop(final T node) {
+    public <T extends Node> T pop(final T node) {
         final T popped = super.pop(node);
         if (isEnabled) {
             if(node instanceof FunctionNode) {
diff --git a/src/jdk/nashorn/internal/ir/RuntimeNode.java b/src/jdk/nashorn/internal/ir/RuntimeNode.java
index 4eca8ff..f372b7f 100644
--- a/src/jdk/nashorn/internal/ir/RuntimeNode.java
+++ b/src/jdk/nashorn/internal/ir/RuntimeNode.java
@@ -25,12 +25,9 @@
 
 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.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;
@@ -40,7 +37,7 @@
  * IR representation for a runtime call.
  */
 @Immutable
-public class RuntimeNode extends Expression implements Optimistic {
+public class RuntimeNode extends Expression {
     private static final long serialVersionUID = 1L;
 
     /**
@@ -59,6 +56,8 @@
         REFERENCE_ERROR,
         /** Delete operator */
         DELETE(TokenType.DELETE, Type.BOOLEAN, 1),
+        /** Delete operator for slow scopes */
+        SLOW_DELETE(TokenType.DELETE, Type.BOOLEAN, 1, false),
         /** Delete operator that always fails -- see Lower */
         FAIL_DELETE(TokenType.DELETE, Type.BOOLEAN, 1, false),
         /** === operator with at least one object */
@@ -277,7 +276,7 @@
          *
          * @param request a request
          *
-         * @return the inverted rquest, or null if not applicable
+         * @return the inverted request, or null if not applicable
          */
         public static Request invert(final Request request) {
             switch (request) {
@@ -334,11 +333,6 @@
     /** Call arguments. */
     private final List<Expression> args;
 
-    /** is final - i.e. may not be removed again, lower in the code pipeline */
-    private final boolean isFinal;
-
-    private final int programPoint;
-
     /**
      * Constructor
      *
@@ -352,17 +346,13 @@
 
         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, final int programPoint) {
+    private RuntimeNode(final RuntimeNode runtimeNode, final Request request, final List<Expression> args) {
         super(runtimeNode);
 
         this.request      = request;
         this.args         = args;
-        this.isFinal      = isFinal;
-        this.programPoint = programPoint;
     }
 
     /**
@@ -400,8 +390,6 @@
 
         this.request      = request;
         this.args         = args;
-        this.isFinal      = false;
-        this.programPoint = parent instanceof Optimistic ? ((Optimistic)parent).getProgramPoint() : INVALID_PROGRAM_POINT;
     }
 
     /**
@@ -429,38 +417,17 @@
      * @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
-     */
-    public boolean isFinal() {
-        return isFinal;
-    }
-
-    /**
-     * Flag this node as final - i.e it may never be replaced with other nodes again
-     * @param isFinal is the node final, i.e. can not be removed and replaced by a less generic one later in codegen
-     * @return same runtime node if already final, otherwise a new one
-     */
-    public RuntimeNode setIsFinal(final boolean isFinal) {
-        if (this.isFinal == isFinal) {
+        if (this.request == request) {
             return this;
         }
-        return new RuntimeNode(this, request, isFinal, args, programPoint);
-    }
+        return new RuntimeNode(this, request, args);
+   }
 
     /**
      * Return type for the ReferenceNode
      */
     @Override
-    public Type getType(final Function<Symbol, Type> localVariableTypes) {
+    public Type getType() {
         return request.getReturnType();
     }
 
@@ -511,7 +478,7 @@
         if (this.args == args) {
             return this;
         }
-        return new RuntimeNode(this, request, isFinal, args, programPoint);
+        return new RuntimeNode(this, request, args);
     }
 
     /**
@@ -537,39 +504,4 @@
         }
         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/src/jdk/nashorn/internal/ir/SplitReturn.java b/src/jdk/nashorn/internal/ir/SplitReturn.java
index fb1b58c..d60aa60 100644
--- a/src/jdk/nashorn/internal/ir/SplitReturn.java
+++ b/src/jdk/nashorn/internal/ir/SplitReturn.java
@@ -54,7 +54,7 @@
     }
 
     @Override
-    public void toString(StringBuilder sb, boolean printType) {
+    public void toString(final StringBuilder sb, final boolean printType) {
         sb.append(":splitreturn;");
     }
 
diff --git a/src/jdk/nashorn/internal/ir/Splittable.java b/src/jdk/nashorn/internal/ir/Splittable.java
new file mode 100644
index 0000000..d331171
--- /dev/null
+++ b/src/jdk/nashorn/internal/ir/Splittable.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.io.Serializable;
+import java.util.List;
+import jdk.nashorn.internal.codegen.CompileUnit;
+
+/**
+ * An interface for splittable expressions.
+ */
+public interface Splittable {
+
+    /**
+     * Get a list of split ranges for this splittable expression, or null
+     * if the expression should not be split.
+     *
+     * @return a list of split ranges
+     */
+    List<SplitRange> getSplitRanges();
+
+    /**
+     * A SplitRange is a range in a splittable expression. It defines the
+     * boundaries of the split range and provides a compile unit for code generation.
+     */
+    final class SplitRange implements CompileUnitHolder, Serializable {
+        private static final long serialVersionUID = 1L;
+
+        /** Compile unit associated with the postsets range. */
+        private final CompileUnit compileUnit;
+
+        /** postsets range associated with the unit (hi not inclusive). */
+        private final int low, high;
+
+        /**
+         * Constructor
+         * @param compileUnit compile unit
+         * @param low lowest array index in unit
+         * @param high highest array index in unit + 1
+         */
+        public SplitRange(final CompileUnit compileUnit, final int low, final int high) {
+            this.compileUnit = compileUnit;
+            this.low   = low;
+            this.high   = high;
+        }
+
+        /**
+         * Get the high index position of the ArrayUnit (exclusive)
+         * @return high index position
+         */
+        public int getHigh() {
+            return high;
+        }
+
+        /**
+         * Get the low index position of the ArrayUnit (inclusive)
+         * @return low index position
+         */
+        public int getLow() {
+            return low;
+        }
+
+        /**
+         * The array compile unit
+         * @return array compile unit
+         */
+        @Override
+        public CompileUnit getCompileUnit() {
+            return compileUnit;
+        }
+    }
+}
diff --git a/src/jdk/nashorn/internal/ir/SwitchNode.java b/src/jdk/nashorn/internal/ir/SwitchNode.java
index ca44758..4f25151 100644
--- a/src/jdk/nashorn/internal/ir/SwitchNode.java
+++ b/src/jdk/nashorn/internal/ir/SwitchNode.java
@@ -53,7 +53,7 @@
     private final boolean uniqueInteger;
 
     /** Tag symbol. */
-    private Symbol tag;
+    private final Symbol tag;
 
     /**
      * Constructor
@@ -71,15 +71,16 @@
         this.cases            = cases;
         this.defaultCaseIndex = defaultCase == null ? -1 : cases.indexOf(defaultCase);
         this.uniqueInteger    = false;
+        this.tag = null;
     }
 
     private SwitchNode(final SwitchNode switchNode, final Expression expression, final List<CaseNode> cases,
-            final int defaultCaseIndex, final LocalVariableConversion conversion, final boolean uniqueInteger) {
+            final int defaultCaseIndex, final LocalVariableConversion conversion, final boolean uniqueInteger, final Symbol tag) {
         super(switchNode, conversion);
         this.expression       = expression;
         this.cases            = cases;
         this.defaultCaseIndex = defaultCaseIndex;
-        this.tag              = switchNode.getTag(); //TODO are symbols inherited as references?
+        this.tag              = tag;
         this.uniqueInteger    = uniqueInteger;
     }
 
@@ -89,7 +90,7 @@
         for (final CaseNode caseNode : cases) {
             newCases.add(new CaseNode(caseNode, caseNode.getTest(), caseNode.getBody(), caseNode.getLocalVariableConversion()));
         }
-        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, newCases, defaultCaseIndex, conversion, uniqueInteger));
+        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, newCases, defaultCaseIndex, conversion, uniqueInteger, tag));
     }
 
     @Override
@@ -157,7 +158,7 @@
         if (this.cases == cases) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger));
+        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag));
     }
 
     /**
@@ -189,7 +190,7 @@
         if (this.expression == expression) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger));
+        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag));
     }
 
     /**
@@ -204,10 +205,15 @@
     /**
      * Set the tag symbol for this switch. The tag symbol is where
      * the switch expression result is stored
+     * @param lc lexical context
      * @param tag a symbol
+     * @return a switch node with the symbol set
      */
-    public void setTag(final Symbol tag) {
-        this.tag = tag;
+    public SwitchNode setTag(final LexicalContext lc, final Symbol tag) {
+        if (this.tag == tag) {
+            return this;
+        }
+        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag));
     }
 
     /**
@@ -229,12 +235,12 @@
         if(this.uniqueInteger == uniqueInteger) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger));
+        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag));
     }
 
     @Override
     JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) {
-        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger));
+        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion, uniqueInteger, tag));
     }
 
 }
diff --git a/src/jdk/nashorn/internal/ir/Symbol.java b/src/jdk/nashorn/internal/ir/Symbol.java
index d4ccd45..c33a4ba 100644
--- a/src/jdk/nashorn/internal/ir/Symbol.java
+++ b/src/jdk/nashorn/internal/ir/Symbol.java
@@ -25,7 +25,10 @@
 
 package jdk.nashorn.internal.ir;
 
+import java.io.IOException;
+import java.io.ObjectInputStream;
 import java.io.PrintWriter;
+import java.io.Serializable;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.StringTokenizer;
@@ -47,7 +50,9 @@
  * refer to their location.
  */
 
-public final class Symbol implements Comparable<Symbol> {
+public final class Symbol implements Comparable<Symbol>, Cloneable, Serializable {
+    private static final long serialVersionUID = 1L;
+
     /** Is this Global */
     public static final int IS_GLOBAL   = 1;
     /** Is this a variable */
@@ -94,10 +99,10 @@
 
     /** 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;
+    private transient int firstSlot = -1;
 
     /** Field number in scope or property; array index in varargs when not using arguments object. */
-    private int fieldIndex = -1;
+    private transient int fieldIndex = -1;
 
     /** Number of times this symbol is used in code */
     private int useCount;
@@ -144,6 +149,15 @@
         }
     }
 
+    @Override
+    public Symbol clone() {
+        try {
+            return (Symbol)super.clone();
+        } catch (final CloneNotSupportedException e) {
+            throw new AssertionError(e);
+        }
+    }
+
     private static String align(final String string, final int max) {
         final StringBuilder sb = new StringBuilder();
         sb.append(string.substring(0, Math.min(string.length(), max)));
@@ -337,7 +351,7 @@
      * Flag this symbol as scope as described in {@link Symbol#isScope()}
      * @return the symbol
      */
-     public Symbol setIsScope() {
+    public Symbol setIsScope() {
         if (!isScope()) {
             if(shouldTrace()) {
                 trace("SET IS SCOPE");
@@ -609,11 +623,11 @@
 
     /**
      * Increase the symbol's use count by one.
-     * @return the symbol
      */
-    public Symbol increaseUseCount() {
-        useCount++;
-        return this;
+    public void increaseUseCount() {
+        if (isScope()) { // Avoid dirtying a cache line; we only need the use count for scoped symbols
+            useCount++;
+        }
     }
 
     /**
@@ -669,4 +683,10 @@
             new Throwable().printStackTrace(Context.getCurrentErr());
         }
     }
+
+    private void readObject(final ObjectInputStream in) throws ClassNotFoundException, IOException {
+        in.defaultReadObject();
+        firstSlot = -1;
+        fieldIndex = -1;
+    }
 }
diff --git a/src/jdk/nashorn/internal/ir/TernaryNode.java b/src/jdk/nashorn/internal/ir/TernaryNode.java
index 913262d..e3bca0b 100644
--- a/src/jdk/nashorn/internal/ir/TernaryNode.java
+++ b/src/jdk/nashorn/internal/ir/TernaryNode.java
@@ -25,7 +25,6 @@
 
 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;
@@ -122,8 +121,8 @@
     }
 
     @Override
-    public Type getType(final Function<Symbol, Type> localVariableTypes) {
-        return Type.widestReturnType(getTrueExpression().getType(localVariableTypes), getFalseExpression().getType(localVariableTypes));
+    public Type getType() {
+        return Type.widestReturnType(getTrueExpression().getType(), getFalseExpression().getType());
     }
 
 
diff --git a/src/jdk/nashorn/internal/ir/TryNode.java b/src/jdk/nashorn/internal/ir/TryNode.java
index 605e0a9..661281e 100644
--- a/src/jdk/nashorn/internal/ir/TryNode.java
+++ b/src/jdk/nashorn/internal/ir/TryNode.java
@@ -27,7 +27,9 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 
@@ -35,7 +37,7 @@
  * IR representation of a TRY statement.
  */
 @Immutable
-public final class TryNode extends Statement implements JoinPredecessor {
+public final class TryNode extends LexicalContextStatement implements JoinPredecessor {
     private static final long serialVersionUID = 1L;
 
     /** Try statements. */
@@ -47,11 +49,23 @@
     /** Finally clause. */
     private final Block finallyBody;
 
-    /** Exception symbol. */
-    private Symbol exception;
+    /**
+     * List of inlined finally blocks. The structure of every inlined finally is:
+     * Block(LabelNode(label, Block(finally-statements, (JumpStatement|ReturnNode)?))).
+     * That is, the block has a single LabelNode statement with the label and a block containing the
+     * statements of the inlined finally block with the jump or return statement appended (if the finally
+     * block was not terminal; the original jump/return is simply ignored if the finally block itself
+     * terminates). The reason for this somewhat strange arrangement is that we didn't want to create a
+     * separate class for the (label, BlockStatement pair) but rather reused the already available LabelNode.
+     * However, if we simply used List&lt;LabelNode&gt; without wrapping the label nodes in an additional Block,
+     * that would've thrown off visitors relying on BlockLexicalContext -- same reason why we never use
+     * Statement as the type of bodies of e.g. IfNode, WhileNode etc. but rather blockify them even when they're
+     * single statements.
+     */
+    private final List<Block> inlinedFinallies;
 
-    /** Catchall exception for finally expansion, where applicable */
-    private Symbol finallyCatchAll;
+    /** Exception symbol. */
+    private final Symbol exception;
 
     private final LocalVariableConversion conversion;
 
@@ -71,21 +85,24 @@
         this.catchBlocks = catchBlocks;
         this.finallyBody = finallyBody;
         this.conversion  = null;
+        this.inlinedFinallies = Collections.emptyList();
+        this.exception = null;
     }
 
-    private TryNode(final TryNode tryNode, final Block body, final List<Block> catchBlocks, final Block finallyBody, final LocalVariableConversion conversion) {
+    private TryNode(final TryNode tryNode, final Block body, final List<Block> catchBlocks, final Block finallyBody, final LocalVariableConversion conversion, final List<Block> inlinedFinallies, final Symbol exception) {
         super(tryNode);
         this.body        = body;
         this.catchBlocks = catchBlocks;
         this.finallyBody = finallyBody;
         this.conversion  = conversion;
-        this.exception = tryNode.exception;
+        this.inlinedFinallies = inlinedFinallies;
+        this.exception = exception;
     }
 
     @Override
     public Node ensureUniqueLabels(final LexicalContext lc) {
         //try nodes are never in lex context
-        return new TryNode(this, body, catchBlocks, finallyBody, conversion);
+        return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception);
     }
 
     @Override
@@ -106,16 +123,16 @@
      * @param visitor IR navigating visitor.
      */
     @Override
-    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterTryNode(this)) {
             // Need to do finallybody first for termination analysis. TODO still necessary?
             final Block newFinallyBody = finallyBody == null ? null : (Block)finallyBody.accept(visitor);
             final Block newBody        = (Block)body.accept(visitor);
             return visitor.leaveTryNode(
-                setBody(newBody).
-                setFinallyBody(newFinallyBody).
-                setCatchBlocks(Node.accept(visitor, catchBlocks)).
-                setFinallyCatchAll(finallyCatchAll));
+                setBody(lc, newBody).
+                setFinallyBody(lc, newFinallyBody).
+                setCatchBlocks(lc, Node.accept(visitor, catchBlocks)).
+                setInlinedFinallies(lc, Node.accept(visitor, inlinedFinallies)));
         }
 
         return this;
@@ -136,14 +153,15 @@
 
     /**
      * Reset the body of this try block
+     * @param lc current lexical context
      * @param body new body
      * @return new TryNode or same if unchanged
      */
-    public TryNode setBody(final Block body) {
+    public TryNode setBody(final LexicalContext lc, final Block body) {
         if (this.body == body) {
             return this;
         }
-        return new TryNode(this,  body, catchBlocks, finallyBody, conversion);
+        return Node.replaceInLexicalContext(lc, this, new TryNode(this,  body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception));
     }
 
     /**
@@ -172,14 +190,15 @@
 
     /**
      * Set the catch blocks of this try
+     * @param lc current lexical context
      * @param catchBlocks list of catch blocks
      * @return new TryNode or same if unchanged
      */
-    public TryNode setCatchBlocks(final List<Block> catchBlocks) {
+    public TryNode setCatchBlocks(final LexicalContext lc, final List<Block> catchBlocks) {
         if (this.catchBlocks == catchBlocks) {
             return this;
         }
-        return new TryNode(this, body, catchBlocks, finallyBody, conversion);
+        return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception));
     }
 
     /**
@@ -191,33 +210,15 @@
     }
     /**
      * Set the exception symbol for this try block
+     * @param lc lexical context
      * @param exception a symbol for the compiler to store the exception in
      * @return new TryNode or same if unchanged
      */
-    public TryNode setException(final Symbol exception) {
-        this.exception = exception;
-        return this;
-    }
-
-    /**
-     * Get the catch all symbol for this try block
-     * @return catch all symbol
-     */
-    public Symbol getFinallyCatchAll() {
-        return this.finallyCatchAll;
-    }
-
-    /**
-     * If a finally block exists, the synthetic catchall needs another symbol to
-     * store its throwable
-     * @param finallyCatchAll a symbol for the finally catch all exception
-     * @return new TryNode or same if unchanged
-     *
-     * TODO can this still be stateful?
-     */
-    public TryNode setFinallyCatchAll(final Symbol finallyCatchAll) {
-        this.finallyCatchAll = finallyCatchAll;
-        return this;
+    public TryNode setException(final LexicalContext lc, final Symbol exception) {
+        if (this.exception == exception) {
+            return this;
+        }
+        return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception));
     }
 
     /**
@@ -229,15 +230,87 @@
     }
 
     /**
+     * Get the inlined finally block with the given label name. This returns the actual finally block in the
+     * {@link LabelNode}, not the outer wrapper block for the {@link LabelNode}.
+     * @param labelName the name of the inlined finally's label
+     * @return the requested finally block, or null if no finally block's label matches the name.
+     */
+    public Block getInlinedFinally(final String labelName) {
+        for(final Block inlinedFinally: inlinedFinallies) {
+            final LabelNode labelNode = getInlinedFinallyLabelNode(inlinedFinally);
+            if (labelNode.getLabelName().equals(labelName)) {
+                return labelNode.getBody();
+            }
+        }
+        return null;
+    }
+
+    private static LabelNode getInlinedFinallyLabelNode(final Block inlinedFinally) {
+        return (LabelNode)inlinedFinally.getStatements().get(0);
+    }
+
+    /**
+     * Given an outer wrapper block for the {@link LabelNode} as returned by {@link #getInlinedFinallies()},
+     * returns its actual inlined finally block.
+     * @param inlinedFinally the outer block for inlined finally, as returned as an element of
+     * {@link #getInlinedFinallies()}.
+     * @return the block contained in the {@link LabelNode} contained in the passed block.
+     */
+    public static Block getLabelledInlinedFinallyBlock(final Block inlinedFinally) {
+        return getInlinedFinallyLabelNode(inlinedFinally).getBody();
+    }
+
+    /**
+     * Returns a list of inlined finally blocks. Note that this returns a list of {@link Block}s such that each one of
+     * them has a single {@link LabelNode}, which in turn contains the label name for the finally block and the
+     * actual finally block. To safely extract the actual finally block, use
+     * {@link #getLabelledInlinedFinallyBlock(Block)}.
+     * @return a list of inlined finally blocks.
+     */
+    public List<Block> getInlinedFinallies() {
+        return Collections.unmodifiableList(inlinedFinallies);
+    }
+
+    /**
      * Set the finally body of this try
+     * @param lc current lexical context
      * @param finallyBody new finally body
      * @return new TryNode or same if unchanged
      */
-    public TryNode setFinallyBody(final Block finallyBody) {
+    public TryNode setFinallyBody(final LexicalContext lc, final Block finallyBody) {
         if (this.finallyBody == finallyBody) {
             return this;
         }
-        return new TryNode(this, body, catchBlocks, finallyBody, conversion);
+        return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception));
+    }
+
+    /**
+     * Set the inlined finally blocks of this try. Each element should be a block with a single statement that is a
+     * {@link LabelNode} with a unique label, and the block within the label node should contain the actual inlined
+     * finally block.
+     * @param lc current lexical context
+     * @param inlinedFinallies list of inlined finally blocks
+     * @return new TryNode or same if unchanged
+     */
+    public TryNode setInlinedFinallies(final LexicalContext lc, final List<Block> inlinedFinallies) {
+        if (this.inlinedFinallies == inlinedFinallies) {
+            return this;
+        }
+        assert checkInlinedFinallies(inlinedFinallies);
+        return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception));
+    }
+
+    private static boolean checkInlinedFinallies(final List<Block> inlinedFinallies) {
+        if (!inlinedFinallies.isEmpty()) {
+            final Set<String> labels = new HashSet<>();
+            for (final Block inlinedFinally : inlinedFinallies) {
+                final List<Statement> stmts = inlinedFinally.getStatements();
+                assert stmts.size() == 1;
+                final LabelNode ln = getInlinedFinallyLabelNode(inlinedFinally);
+                assert labels.add(ln.getLabelName()); // unique label
+            }
+        }
+        return true;
     }
 
     @Override
@@ -245,7 +318,7 @@
         if(this.conversion == conversion) {
             return this;
         }
-        return new TryNode(this, body, catchBlocks, finallyBody, conversion);
+        return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies, exception);
     }
 
     @Override
diff --git a/src/jdk/nashorn/internal/ir/UnaryNode.java b/src/jdk/nashorn/internal/ir/UnaryNode.java
index 2cee33b..2f7b268 100644
--- a/src/jdk/nashorn/internal/ir/UnaryNode.java
+++ b/src/jdk/nashorn/internal/ir/UnaryNode.java
@@ -33,7 +33,6 @@
 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;
@@ -123,23 +122,11 @@
         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 getWidestOperationType(UNKNOWN_LOCALS);
-    }
-
-    private Type getWidestOperationType(final Function<Symbol, Type> localVariableTypes) {
         switch (tokenType()) {
         case ADD:
-            final Type operandType = getExpression().getType(localVariableTypes);
+            final Type operandType = getExpression().getType();
             if(operandType == Type.BOOLEAN) {
                 return Type.INT;
             } else if(operandType.isObject()) {
@@ -326,12 +313,12 @@
     }
 
     @Override
-    public Type getType(final Function<Symbol, Type> localVariableTypes) {
-        final Type widest = getWidestOperationType(localVariableTypes);
+    public Type getType() {
+        final Type widest = getWidestOperationType();
         if(type == null) {
             return widest;
         }
-        return Type.narrowest(widest, Type.widest(type, expression.getType(localVariableTypes)));
+        return Type.narrowest(widest, Type.widest(type, expression.getType()));
     }
 
     @Override
diff --git a/src/jdk/nashorn/internal/ir/VarNode.java b/src/jdk/nashorn/internal/ir/VarNode.java
index 1cee8cb..17e6467 100644
--- a/src/jdk/nashorn/internal/ir/VarNode.java
+++ b/src/jdk/nashorn/internal/ir/VarNode.java
@@ -27,7 +27,6 @@
 
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import jdk.nashorn.internal.parser.Token;
 
 /**
  * Node represents a var/let declaration.
@@ -182,7 +181,7 @@
 
     @Override
     public void toString(final StringBuilder sb, final boolean printType) {
-        sb.append(Token.descType(getToken()).getName()).append(' ');
+        sb.append(tokenType().getName()).append(' ');
         name.toString(sb, printType);
 
         if (init != null) {
@@ -263,12 +262,4 @@
     public boolean isFunctionDeclaration() {
         return init instanceof FunctionNode && ((FunctionNode)init).isDeclared();
     }
-
-    /**
-     * Returns true if this is an anonymous function declaration.
-     * @return true if this is an anonymous function declaration.
-     */
-    public boolean isAnonymousFunctionDeclaration() {
-        return isFunctionDeclaration() && ((FunctionNode)init).isAnonymous();
-    }
 }
diff --git a/src/jdk/nashorn/internal/ir/debug/JSONWriter.java b/src/jdk/nashorn/internal/ir/debug/JSONWriter.java
index e3916d6..b72d899 100644
--- a/src/jdk/nashorn/internal/ir/debug/JSONWriter.java
+++ b/src/jdk/nashorn/internal/ir/debug/JSONWriter.java
@@ -28,7 +28,6 @@
 import static jdk.nashorn.internal.runtime.Source.sourceFor;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import jdk.nashorn.internal.ir.AccessNode;
 import jdk.nashorn.internal.ir.BinaryNode;
@@ -49,7 +48,6 @@
 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;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.ObjectNode;
@@ -66,7 +64,7 @@
 import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.WhileNode;
 import jdk.nashorn.internal.ir.WithNode;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.parser.JSONParser;
 import jdk.nashorn.internal.parser.Lexer.RegexToken;
 import jdk.nashorn.internal.parser.Parser;
@@ -78,7 +76,7 @@
 /**
  * This IR writer produces a JSON string that represents AST as a JSON string.
  */
-public final class JSONWriter extends NodeVisitor<LexicalContext> {
+public final class JSONWriter extends SimpleNodeVisitor {
 
     /**
      * Returns AST as JSON compatible string.
@@ -553,8 +551,7 @@
             type("ArrayExpression");
             comma();
 
-            final Node[] value = literalNode.getArray();
-            array("elements", Arrays.asList(value));
+            array("elements", ((LiteralNode.ArrayLiteralNode)literalNode).getElementExpressions());
         } else {
             type("Literal");
             comma();
@@ -941,7 +938,6 @@
     // Internals below
 
     private JSONWriter(final boolean includeLocation) {
-        super(new LexicalContext());
         this.buf             = new StringBuilder();
         this.includeLocation = includeLocation;
     }
diff --git a/src/jdk/nashorn/internal/ir/debug/NashornClassReader.java b/src/jdk/nashorn/internal/ir/debug/NashornClassReader.java
index 87eb18d..26d4dc9 100644
--- a/src/jdk/nashorn/internal/ir/debug/NashornClassReader.java
+++ b/src/jdk/nashorn/internal/ir/debug/NashornClassReader.java
@@ -36,7 +36,7 @@
 import jdk.nashorn.internal.ir.debug.NashornTextifier.NashornLabel;
 
 /**
- * Subclass of the ASM classs reader that retains more info, such
+ * Subclass of the ASM class reader that retains more info, such
  * as bytecode offsets
  */
 public class NashornClassReader extends ClassReader {
diff --git a/src/jdk/nashorn/internal/ir/debug/NashornTextifier.java b/src/jdk/nashorn/internal/ir/debug/NashornTextifier.java
index 5cdc67d..c5dc56b 100644
--- a/src/jdk/nashorn/internal/ir/debug/NashornTextifier.java
+++ b/src/jdk/nashorn/internal/ir/debug/NashornTextifier.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1109,7 +1109,7 @@
                 }
                 final String ex = catches.get(node);
                 if (ex != null) {
-                    sb.append("*** CATCH: ").append(ex).append(" ***\n");
+                    sb.append("*** CATCH: ").append(ex).append(" ***\\l");
                 }
                 sb.append(c);
                 sb.append("\"]\n");
diff --git a/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java b/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java
index 53a09a6..24ef303 100644
--- a/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java
+++ b/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java
@@ -38,6 +38,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * Contains utility methods for calculating the memory usage of objects. It
@@ -150,7 +151,7 @@
      * @param memoryLayoutSpecification a description of the JVM memory layout.
      */
     public ObjectSizeCalculator(final MemoryLayoutSpecification memoryLayoutSpecification) {
-        memoryLayoutSpecification.getClass();
+        Objects.requireNonNull(memoryLayoutSpecification);
         arrayHeaderSize = memoryLayoutSpecification.getArrayHeaderSize();
         objectHeaderSize = memoryLayoutSpecification.getObjectHeaderSize();
         objectPadding = memoryLayoutSpecification.getObjectPadding();
@@ -192,7 +193,7 @@
     }
 
     /**
-     * Get the class histograpm
+     * Get the class histogram
      * @return class histogram element list
      */
     public List<ClassHistogramElement> getClassHistogram() {
diff --git a/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java b/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java
index 52e9b66..bb8d61a 100644
--- a/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java
+++ b/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java
@@ -41,7 +41,6 @@
 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;
@@ -53,7 +52,7 @@
 import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.WhileNode;
 import jdk.nashorn.internal.ir.WithNode;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 
 /**
  * Print out the AST as human readable source code.
@@ -61,7 +60,7 @@
  *
  * see the flags --print-parse and --print-lower-parse
  */
-public final class PrintVisitor extends NodeVisitor<LexicalContext> {
+public final class PrintVisitor extends SimpleNodeVisitor {
     /** Tab width */
     private static final int TABWIDTH = 4;
 
@@ -96,7 +95,6 @@
      * @param printTypes        should we print optimistic and inferred types?
      */
     public PrintVisitor(final boolean printLineNumbers, final boolean printTypes) {
-        super(new LexicalContext());
         this.EOLN             = System.lineSeparator();
         this.sb               = new StringBuilder();
         this.printLineNumbers = printLineNumbers;
@@ -391,6 +389,9 @@
             finallyBody.accept(this);
         }
 
+        for (final Block inlinedFinally : tryNode.getInlinedFinallies()) {
+            inlinedFinally.accept(this);
+        }
         return false;
     }
 
diff --git a/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java b/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java
index 1582f30..9badcf6 100644
--- a/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java
+++ b/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java
@@ -34,7 +34,7 @@
  * Like NodeVisitor but navigating further into operators.
  * @param <T> Lexical context class for this NodeOperatorVisitor
  */
-public class NodeOperatorVisitor<T extends LexicalContext> extends NodeVisitor<T> {
+public abstract class NodeOperatorVisitor<T extends LexicalContext> extends NodeVisitor<T> {
     /**
      * Constructor
      *
diff --git a/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java b/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java
index f9fd386..28022b1 100644
--- a/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java
+++ b/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java
@@ -43,6 +43,7 @@
 import jdk.nashorn.internal.ir.IfNode;
 import jdk.nashorn.internal.ir.IndexNode;
 import jdk.nashorn.internal.ir.JoinPredecessorExpression;
+import jdk.nashorn.internal.ir.JumpToInlinedFinally;
 import jdk.nashorn.internal.ir.LabelNode;
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
@@ -473,6 +474,26 @@
     }
 
     /**
+     * Callback for entering a JumpToInlinedFinally
+     *
+     * @param  jumpToInlinedFinally the node
+     * @return true if traversal should continue and node children be traversed, false otherwise
+     */
+    public boolean enterJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+        return enterDefault(jumpToInlinedFinally);
+    }
+
+    /**
+     * Callback for leaving a JumpToInlinedFinally
+     *
+     * @param  jumpToInlinedFinally the node
+     * @return processed node, which will replace the original one, or the original node
+     */
+    public Node leaveJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+        return leaveDefault(jumpToInlinedFinally);
+    }
+
+    /**
      * Callback for entering a LabelNode
      *
      * @param  labelNode the node
diff --git a/test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java b/src/jdk/nashorn/internal/ir/visitor/SimpleNodeVisitor.java
similarity index 71%
copy from test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java
copy to src/jdk/nashorn/internal/ir/visitor/SimpleNodeVisitor.java
index d9a4455..015e1fe 100644
--- a/test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java
+++ b/src/jdk/nashorn/internal/ir/visitor/SimpleNodeVisitor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,15 +23,19 @@
  * questions.
  */
 
-package jdk.internal.dynalink.beans;
+package jdk.nashorn.internal.ir.visitor;
 
-import jdk.nashorn.test.models.ClassLoaderAware;
-import org.testng.annotations.Test;
+import jdk.nashorn.internal.ir.LexicalContext;
 
-@SuppressWarnings("javadoc")
-public class CallerSensitiveTest {
-    @Test
-    public void testCallerSensitive() {
-        BeansLinker.getLinkerForClass(ClassLoaderAware.class);
+/**
+ * Convenience base class for a {@link NodeVisitor} with a plain {@link LexicalContext}.
+ */
+public abstract class SimpleNodeVisitor extends NodeVisitor<LexicalContext> {
+
+    /**
+     * Creates a new simple node visitor.
+     */
+    public SimpleNodeVisitor() {
+        super(new LexicalContext());
     }
 }
diff --git a/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java b/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java
index 8e5120f..2dcc401 100644
--- a/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java
+++ b/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java
@@ -25,6 +25,8 @@
 
 package jdk.nashorn.internal.lookup;
 
+import static jdk.nashorn.internal.runtime.JSType.isString;
+
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
 import java.lang.invoke.MethodHandle;
@@ -36,7 +38,6 @@
 import java.util.Arrays;
 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.ScriptObject;
@@ -130,8 +131,8 @@
     static Object traceReturn(final DebugLogger logger, final Object value) {
         final String str = "    return" +
                 (VOID_TAG.equals(value) ?
-                    ";" :
-                    " " + stripName(value) + "; // [type=" + (value == null ? "null]" : stripName(value.getClass()) + ']'));
+                        ";" :
+                            " " + stripName(value) + "; // [type=" + (value == null ? "null]" : stripName(value.getClass()) + ']'));
         if (logger == null) {
             err(str);
         } else if (logger.isEnabled()) {
@@ -163,13 +164,13 @@
             }
 
             sb.append('\'').
-                append(stripName(argString(args[i]))).
-                append('\'').
-                append(' ').
-                append('[').
-                append("type=").
-                append(args[i] == null ? "null" : stripName(args[i].getClass())).
-                append(']');
+            append(stripName(argString(args[i]))).
+            append('\'').
+            append(' ').
+            append('[').
+            append("type=").
+            append(args[i] == null ? "null" : stripName(args[i].getClass())).
+            append(']');
 
             if (i + 1 < args.length) {
                 sb.append(", ");
@@ -215,8 +216,8 @@
 
         if (arg instanceof ScriptObject) {
             return arg.toString() +
-                " (map=" + Debug.id(((ScriptObject)arg).getMap()) +
-                ')';
+                    " (map=" + Debug.id(((ScriptObject)arg).getMap()) +
+                    ')';
         }
 
         return arg.toString();
@@ -261,7 +262,7 @@
         return addDebugPrintout(null, Level.OFF, mh, paramStart, printReturnValue, 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
@@ -277,7 +278,7 @@
 
         //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)) {
+        if (logger == null || !logger.isLoggable(level)) {
             return mh;
         }
 
@@ -288,9 +289,9 @@
         trace = MethodHandles.foldArguments(
                 mh,
                 trace.asCollector(
-                    Object[].class,
-                    type.parameterCount()).
-                asType(type.changeReturnType(void.class)));
+                        Object[].class,
+                        type.parameterCount()).
+                        asType(type.changeReturnType(void.class)));
 
         final Class<?> retType = type.returnType();
         if (printReturnValue) {
@@ -298,7 +299,7 @@
                 final MethodHandle traceReturn = MethodHandles.insertArguments(TRACE_RETURN, 0, logger);
                 trace = MethodHandles.filterReturnValue(trace,
                         traceReturn.asType(
-                            traceReturn.type().changeParameterType(0, retType).changeReturnType(retType)));
+                                traceReturn.type().changeParameterType(0, retType).changeReturnType(retType)));
             } else {
                 trace = MethodHandles.filterReturnValue(trace, MethodHandles.insertArguments(TRACE_RETURN_VOID, 0, logger));
             }
@@ -343,7 +344,7 @@
                 final Object d = data[i];
                 if (d == null) {
                     sb.append("<null> ");
-                } else if (d instanceof String || d instanceof ConsString) {
+                } else if (isString(d)) {
                     sb.append(d.toString());
                     sb.append(' ');
                 } else if (d.getClass().isArray()) {
@@ -354,9 +355,9 @@
                     sb.append("] ");
                 } else {
                     sb.append(d)
-                        .append('{')
-                        .append(Integer.toHexString(System.identityHashCode(d)))
-                        .append('}');
+                    .append('{')
+                    .append(Integer.toHexString(System.identityHashCode(d)))
+                    .append('}');
                 }
 
                 if (i + 1 < data.length) {
diff --git a/src/jdk/nashorn/internal/objects/ArrayBufferView.java b/src/jdk/nashorn/internal/objects/ArrayBufferView.java
index fa3b807..8f75975 100644
--- a/src/jdk/nashorn/internal/objects/ArrayBufferView.java
+++ b/src/jdk/nashorn/internal/objects/ArrayBufferView.java
@@ -192,7 +192,7 @@
         /**
          * Factory method for array data
          *
-         * @param nb    underlying nativebuffer
+         * @param nb    underlying native buffer
          * @param start start element
          * @param end   end element
          *
diff --git a/src/jdk/nashorn/internal/objects/BoundScriptFunctionImpl.java b/src/jdk/nashorn/internal/objects/BoundScriptFunctionImpl.java
deleted file mode 100644
index 333790f..0000000
--- a/src/jdk/nashorn/internal/objects/BoundScriptFunctionImpl.java
+++ /dev/null
@@ -1,51 +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.objects;
-
-import jdk.nashorn.internal.runtime.ScriptFunction;
-import jdk.nashorn.internal.runtime.ScriptFunctionData;
-import jdk.nashorn.internal.runtime.ScriptObject;
-import jdk.nashorn.internal.runtime.ScriptRuntime;
-
-/**
- * A {@code ScriptFunctionImpl} subclass for functions created using {@code Function.prototype.bind}. Such functions
- * must track their {@code [[TargetFunction]]} property for purposes of correctly implementing {@code [[HasInstance]]};
- * see {@link ScriptFunction#isInstance(ScriptObject)}.
- */
-final class BoundScriptFunctionImpl extends ScriptFunctionImpl {
-    private final ScriptFunction targetFunction;
-
-    BoundScriptFunctionImpl(final ScriptFunctionData data, final ScriptFunction targetFunction) {
-        super(data, Global.instance());
-        setPrototype(ScriptRuntime.UNDEFINED);
-        this.targetFunction = targetFunction;
-    }
-
-    @Override
-    protected ScriptFunction getTargetFunction() {
-        return targetFunction;
-    }
-}
diff --git a/src/jdk/nashorn/internal/objects/Global.java b/src/jdk/nashorn/internal/objects/Global.java
index bb3e13d..8745ec8 100644
--- a/src/jdk/nashorn/internal/objects/Global.java
+++ b/src/jdk/nashorn/internal/objects/Global.java
@@ -28,6 +28,7 @@
 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.isString;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
 import java.io.IOException;
@@ -41,6 +42,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
 import javax.script.ScriptContext;
@@ -52,11 +54,13 @@
 import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import jdk.nashorn.internal.lookup.Lookup;
 import jdk.nashorn.internal.objects.annotations.Attribute;
+import jdk.nashorn.internal.objects.annotations.Getter;
 import jdk.nashorn.internal.objects.annotations.Property;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
-import jdk.nashorn.internal.runtime.ConsString;
+import jdk.nashorn.internal.objects.annotations.Setter;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ECMAErrors;
+import jdk.nashorn.internal.runtime.FindProperty;
 import jdk.nashorn.internal.runtime.GlobalConstants;
 import jdk.nashorn.internal.runtime.GlobalFunctions;
 import jdk.nashorn.internal.runtime.JSType;
@@ -75,15 +79,20 @@
 import jdk.nashorn.internal.runtime.linker.InvokeByName;
 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
 import jdk.nashorn.internal.runtime.regexp.RegExpResult;
+import jdk.nashorn.internal.scripts.JD;
 import jdk.nashorn.internal.scripts.JO;
+import jdk.nashorn.tools.ShellFunctions;
 
 /**
  * Representation of global scope.
  */
 @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();
+public final class Global extends Scope {
+    // This special value is used to flag a lazily initialized global property.
+    // This also serves as placeholder value used in place of a location property
+    // (__FILE__, __DIR__, __LINE__)
+    private static final Object LAZY_SENTINEL = new Object();
+
     private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
     private final InvokeByName VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
 
@@ -173,15 +182,15 @@
 
     /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public final double NaN = Double.NaN;
+    public static 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 double Infinity = Double.POSITIVE_INFINITY;
+    public static 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)
-    public final Object undefined = UNDEFINED;
+    public static final Object undefined = UNDEFINED;
 
     /** ECMA 15.1.2.1 eval(x) */
     @Property(attributes = Attribute.NOT_ENUMERABLE)
@@ -211,21 +220,117 @@
     @Property(name = "Number", attributes = Attribute.NOT_ENUMERABLE)
     public volatile Object number;
 
-    /** ECMA 15.1.4.7 Date constructor */
-    @Property(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
-    public volatile Object date;
+    /**
+     * Getter for ECMA 15.1.4.7 Date property
+     *
+     * @param self self reference
+     * @return Date property value
+     */
+    @Getter(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
+    public static Object getDate(final Object self) {
+        final Global global = Global.instanceFrom(self);
+        if (global.date == LAZY_SENTINEL) {
+            global.date = global.getBuiltinDate();
+        }
+        return global.date;
+    }
 
-    /** ECMA 15.1.4.8 RegExp constructor */
-    @Property(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
-    public volatile Object regexp;
+    /**
+     * Setter for ECMA 15.1.4.7 Date property
+     *
+     * @param self self reference
+     * @param value value for the Date property
+     */
+    @Setter(name = "Date", attributes = Attribute.NOT_ENUMERABLE)
+    public static void setDate(final Object self, final Object value) {
+        final Global global = Global.instanceFrom(self);
+        global.date = value;
+    }
 
-    /** ECMA 15.12 - The JSON object */
-    @Property(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
-    public volatile Object json;
+    private volatile Object date = LAZY_SENTINEL;
 
-    /** Nashorn extension: global.JSAdapter */
-    @Property(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
-    public volatile Object jsadapter;
+    /**
+     * Getter for ECMA 15.1.4.8 RegExp property
+     *
+     * @param self self reference
+     * @return RegExp property value
+     */
+    @Getter(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
+    public static Object getRegExp(final Object self) {
+        final Global global = Global.instanceFrom(self);
+        if (global.regexp == LAZY_SENTINEL) {
+            global.regexp = global.getBuiltinRegExp();
+        }
+        return global.regexp;
+    }
+
+    /**
+     * Setter for ECMA 15.1.4.8 RegExp property
+     *
+     * @param self self reference
+     * @param value value for the RegExp property
+     */
+    @Setter(name = "RegExp", attributes = Attribute.NOT_ENUMERABLE)
+    public static void setRegExp(final Object self, final Object value) {
+        final Global global = Global.instanceFrom(self);
+        global.regexp = value;
+    }
+
+    private volatile Object regexp = LAZY_SENTINEL;
+
+    /**
+     * Getter for ECMA 15.12 - The JSON property
+     * @param self self reference
+     * @return the value of JSON property
+     */
+    @Getter(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
+    public static Object getJSON(final Object self) {
+        final Global global = Global.instanceFrom(self);
+        if (global.json == LAZY_SENTINEL) {
+            global.json = global.getBuiltinJSON();
+        }
+        return global.json;
+    }
+
+    /**
+     * Setter for ECMA 15.12 - The JSON property
+     * @param self self reference
+     * @param value value for the JSON property
+     */
+    @Setter(name = "JSON", attributes = Attribute.NOT_ENUMERABLE)
+    public static void setJSON(final Object self, final Object value) {
+        final Global global = Global.instanceFrom(self);
+        global.json = value;
+    }
+
+    private volatile Object json = LAZY_SENTINEL;
+
+    /**
+     * Getter for Nashorn extension: global.JSAdapter
+     * @param self self reference
+     * @return value of the JSAdapter property
+     */
+    @Getter(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
+    public static Object getJSAdapter(final Object self) {
+        final Global global = Global.instanceFrom(self);
+        if (global.jsadapter == LAZY_SENTINEL) {
+            global.jsadapter = global.getBuiltinJSAdapter();
+        }
+        return global.jsadapter;
+    }
+
+    /**
+     * Setter for Nashorn extension: global.JSAdapter
+     * @param self self reference
+     * @param value value for the JSAdapter property
+     */
+    @Setter(name = "JSAdapter", attributes = Attribute.NOT_ENUMERABLE)
+    public static void setJSAdapter(final Object self, final Object value) {
+        final Global global = Global.instanceFrom(self);
+        global.jsadapter = value;
+    }
+
+    private volatile Object jsadapter = LAZY_SENTINEL;
 
     /** ECMA 15.8 - The Math object */
     @Property(name = "Math", attributes = Attribute.NOT_ENUMERABLE)
@@ -235,13 +340,60 @@
     @Property(name = "Error", attributes = Attribute.NOT_ENUMERABLE)
     public volatile Object error;
 
-    /** EvalError object */
-    @Property(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
-    public volatile Object evalError;
+    /**
+     * Getter for the EvalError property
+     * @param self self reference
+     * @return the value of EvalError property
+     */
+    @Getter(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
+    public static Object getEvalError(final Object self) {
+        final Global global = Global.instanceFrom(self);
+        if (global.evalError == LAZY_SENTINEL) {
+            global.evalError = global.getBuiltinEvalError();
+        }
+        return global.evalError;
+    }
 
-    /** RangeError object */
-    @Property(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
-    public volatile Object rangeError;
+    /**
+     * Setter for the EvalError property
+     * @param self self reference
+     * @param value value of the EvalError property
+     */
+    @Setter(name = "EvalError", attributes = Attribute.NOT_ENUMERABLE)
+    public static void setEvalError(final Object self, final Object value) {
+        final Global global = Global.instanceFrom(self);
+        global.evalError = value;
+    }
+
+    private volatile Object evalError = LAZY_SENTINEL;
+
+    /**
+     * Getter for the RangeError property.
+     * @param self self reference
+     * @return the value of RangeError property
+     */
+    @Getter(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
+    public static Object getRangeError(final Object self) {
+        final Global global = Global.instanceFrom(self);
+        if (global.rangeError == LAZY_SENTINEL) {
+            global.rangeError = global.getBuiltinRangeError();
+        }
+        return global.rangeError;
+    }
+
+
+    /**
+     * Setter for the RangeError property.
+     * @param self self reference
+     * @param value value for the RangeError property
+     */
+    @Setter(name = "RangeError", attributes = Attribute.NOT_ENUMERABLE)
+    public static void setRangeError(final Object self, final Object value) {
+        final Global global = Global.instanceFrom(self);
+        global.rangeError = value;
+    }
+
+    private volatile Object rangeError = LAZY_SENTINEL;
 
     /** ReferenceError object */
     @Property(name = "ReferenceError", attributes = Attribute.NOT_ENUMERABLE)
@@ -255,53 +407,340 @@
     @Property(name = "TypeError", attributes = Attribute.NOT_ENUMERABLE)
     public volatile Object typeError;
 
-    /** URIError object */
-    @Property(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
-    public volatile Object uriError;
+    /**
+     * Getter for the URIError property.
+     * @param self self reference
+     * @return the value of URIError property
+     */
+    @Getter(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
+    public static Object getURIError(final Object self) {
+        final Global global = Global.instanceFrom(self);
+        if (global.uriError == LAZY_SENTINEL) {
+            global.uriError = global.getBuiltinURIError();
+        }
+        return global.uriError;
+    }
 
-    /** ArrayBuffer object */
-    @Property(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
-    public volatile Object arrayBuffer;
+    /**
+     * Setter for the URIError property.
+     * @param self self reference
+     * @param value value for the URIError property
+     */
+    @Setter(name = "URIError", attributes = Attribute.NOT_ENUMERABLE)
+    public static void setURIError(final Object self, final Object value) {
+        final Global global = Global.instanceFrom(self);
+        global.uriError = value;
+    }
 
-    /** DataView object */
-    @Property(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
-    public volatile Object dataView;
+    private volatile Object uriError = LAZY_SENTINEL;
 
-    /** TypedArray (int8) */
-    @Property(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
-    public volatile Object int8Array;
+    /**
+     * Getter for the ArrayBuffer property.
+     * @param self self reference
+     * @return the value of the ArrayBuffer property
+     */
+    @Getter(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
+    public static Object getArrayBuffer(final Object self) {
+        final Global global = Global.instanceFrom(self);
+        if (global.arrayBuffer == LAZY_SENTINEL) {
+            global.arrayBuffer = global.getBuiltinArrayBuffer();
+        }
+        return global.arrayBuffer;
+    }
 
-    /** TypedArray (uint8) */
-    @Property(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
-    public volatile Object uint8Array;
+    /**
+     * Setter for the ArrayBuffer property.
+     * @param self self reference
+     * @param value value of the ArrayBuffer property
+     */
+    @Setter(name = "ArrayBuffer", attributes = Attribute.NOT_ENUMERABLE)
+    public static void setArrayBuffer(final Object self, final Object value) {
+        final Global global = Global.instanceFrom(self);
+        global.arrayBuffer = value;
+    }
 
-    /** TypedArray (uint8) - Clamped */
-    @Property(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
-    public volatile Object uint8ClampedArray;
+    private volatile Object arrayBuffer;
 
-    /** TypedArray (int16) */
-    @Property(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
-    public volatile Object int16Array;
+    /**
+     * Getter for the DataView property.
+     * @param self self reference
+     * @return the value of the DataView property
+     */
+    @Getter(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
+    public static Object getDataView(final Object self) {
+        final Global global = Global.instanceFrom(self);
+        if (global.dataView == LAZY_SENTINEL) {
+            global.dataView = global.getBuiltinDataView();
+        }
+        return global.dataView;
+    }
 
-    /** TypedArray (uint16) */
-    @Property(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
-    public volatile Object uint16Array;
 
-    /** TypedArray (int32) */
-    @Property(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
-    public volatile Object int32Array;
+    /**
+     * Setter for the DataView property.
+     * @param self self reference
+     * @param value value of the DataView property
+     */
+    @Setter(name = "DataView", attributes = Attribute.NOT_ENUMERABLE)
+    public static void setDataView(final Object self, final Object value) {
+        final Global global = Global.instanceFrom(self);
+        global.dataView = value;
+    }
 
-    /** TypedArray (uint32) */
-    @Property(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
-    public volatile Object uint32Array;
+    private volatile Object dataView;
 
-    /** TypedArray (float32) */
-    @Property(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
-    public volatile Object float32Array;
+    /**
+     * Getter for the Int8Array property.
+     * @param self self reference
+     * @return the value of the Int8Array property.
+     */
+    @Getter(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
+    public static Object getInt8Array(final Object self) {
+        final Global global = Global.instanceFrom(self);
+        if (global.int8Array == LAZY_SENTINEL) {
+            global.int8Array = global.getBuiltinInt8Array();
+        }
+        return global.int8Array;
+    }
 
-    /** TypedArray (float64) */
-    @Property(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
-    public volatile Object float64Array;
+    /**
+     * Setter for the Int8Array property.
+     * @param self self reference
+     * @param value value of the Int8Array property
+     */
+    @Setter(name = "Int8Array", attributes = Attribute.NOT_ENUMERABLE)
+    public static void setInt8Array(final Object self, final Object value) {
+        final Global global = Global.instanceFrom(self);
+        global.int8Array = value;
+    }
+
+    private volatile Object int8Array;
+
+    /**
+     * Getter for the Uin8Array property.
+     * @param self self reference
+     * @return the value of the Uint8Array property
+     */
+    @Getter(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
+    public static Object getUint8Array(final Object self) {
+        final Global global = Global.instanceFrom(self);
+        if (global.uint8Array == LAZY_SENTINEL) {
+            global.uint8Array = global.getBuiltinUint8Array();
+        }
+        return global.uint8Array;
+    }
+
+    /**
+     * Setter for the Uin8Array property.
+     * @param self self reference
+     * @param value value of the Uin8Array property
+     */
+    @Setter(name = "Uint8Array", attributes = Attribute.NOT_ENUMERABLE)
+    public static void setUint8Array(final Object self, final Object value) {
+        final Global global = Global.instanceFrom(self);
+        global.uint8Array = value;
+    }
+
+    private volatile Object uint8Array;
+
+    /**
+     * Getter for the Uint8ClampedArray property.
+     * @param self self reference
+     * @return the value of the Uint8ClampedArray property
+     */
+    @Getter(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
+    public static Object getUint8ClampedArray(final Object self) {
+        final Global global = Global.instanceFrom(self);
+        if (global.uint8ClampedArray == LAZY_SENTINEL) {
+            global.uint8ClampedArray = global.getBuiltinUint8ClampedArray();
+        }
+        return global.uint8ClampedArray;
+    }
+
+    /**
+     * Setter for the Uint8ClampedArray property.
+     * @param self self reference
+     * @param value value of the Uint8ClampedArray property
+     */
+    @Setter(name = "Uint8ClampedArray", attributes = Attribute.NOT_ENUMERABLE)
+    public static void setUint8ClampedArray(final Object self, final Object value) {
+        final Global global = Global.instanceFrom(self);
+        global.uint8ClampedArray = value;
+    }
+
+    private volatile Object uint8ClampedArray;
+
+    /**
+     * Getter for the Int16Array property.
+     * @param self self reference
+     * @return the value of the Int16Array property
+     */
+    @Getter(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
+    public static Object getInt16Array(final Object self) {
+        final Global global = Global.instanceFrom(self);
+        if (global.int16Array == LAZY_SENTINEL) {
+            global.int16Array = global.getBuiltinInt16Array();
+        }
+        return global.int16Array;
+    }
+
+    /**
+     * Setter for the Int16Array property.
+     * @param self self reference
+     * @param value value of the Int16Array property
+     */
+    @Setter(name = "Int16Array", attributes = Attribute.NOT_ENUMERABLE)
+    public static void setInt16Array(final Object self, final Object value) {
+        final Global global = Global.instanceFrom(self);
+        global.int16Array = value;
+    }
+
+    private volatile Object int16Array;
+
+    /**
+     * Getter for the Uint16Array property.
+     * @param self self reference
+     * @return the value of the Uint16Array property
+     */
+    @Getter(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
+    public static Object getUint16Array(final Object self) {
+        final Global global = Global.instanceFrom(self);
+        if (global.uint16Array == LAZY_SENTINEL) {
+            global.uint16Array = global.getBuiltinUint16Array();
+        }
+        return global.uint16Array;
+    }
+
+    /**
+     * Setter for the Uint16Array property.
+     * @param self self reference
+     * @param value value of the Uint16Array property
+     */
+    @Setter(name = "Uint16Array", attributes = Attribute.NOT_ENUMERABLE)
+    public static void setUint16Array(final Object self, final Object value) {
+        final Global global = Global.instanceFrom(self);
+        global.uint16Array = value;
+    }
+
+    private volatile Object uint16Array;
+
+    /**
+     * Getter for the Int32Array property.
+     *
+     * @param self self reference
+     * @return the value of the Int32Array property
+     */
+    @Getter(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
+    public static Object getInt32Array(final Object self) {
+        final Global global = Global.instanceFrom(self);
+        if (global.int32Array == LAZY_SENTINEL) {
+            global.int32Array = global.getBuiltinInt32Array();
+        }
+        return global.int32Array;
+    }
+
+
+    /**
+     * Setter for the Int32Array property.
+     *
+     * @param self self reference
+     * @param value value of the Int32Array property
+     */
+    @Setter(name = "Int32Array", attributes = Attribute.NOT_ENUMERABLE)
+    public static void setInt32Array(final Object self, final Object value) {
+        final Global global = Global.instanceFrom(self);
+        global.int32Array = value;
+    }
+
+    private volatile Object int32Array;
+
+    /**
+     * Getter of the Uint32Array property.
+     *
+     * @param self self reference
+     * @return the value of the Uint32Array property
+     */
+    @Getter(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
+    public static Object getUint32Array(final Object self) {
+        final Global global = Global.instanceFrom(self);
+        if (global.uint32Array == LAZY_SENTINEL) {
+            global.uint32Array = global.getBuiltinUint32Array();
+        }
+        return global.uint32Array;
+    }
+
+
+    /**
+     * Setter of the Uint32Array property.
+     *
+     * @param self self reference
+     * @param value value of the Uint32Array property
+     */
+    @Setter(name = "Uint32Array", attributes = Attribute.NOT_ENUMERABLE)
+    public static void setUint32Array(final Object self, final Object value) {
+        final Global global = Global.instanceFrom(self);
+        global.uint32Array = value;
+    }
+
+    private volatile Object uint32Array;
+
+    /**
+     * Getter for the Float32Array property.
+     *
+     * @param self self reference
+     * @return the value of the Float32Array property
+     */
+    @Getter(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
+    public static Object getFloat32Array(final Object self) {
+        final Global global = Global.instanceFrom(self);
+        if (global.float32Array == LAZY_SENTINEL) {
+            global.float32Array = global.getBuiltinFloat32Array();
+        }
+        return global.float32Array;
+    }
+
+    /**
+     * Setter for the Float32Array property.
+     *
+     * @param self self reference
+     * @param value value of the Float32Array property
+     */
+    @Setter(name = "Float32Array", attributes = Attribute.NOT_ENUMERABLE)
+    public static void setFloat32Array(final Object self, final Object value) {
+        final Global global = Global.instanceFrom(self);
+        global.float32Array = value;
+    }
+
+    private volatile Object float32Array;
+
+    /**
+     * Getter for the Float64Array property.
+     *
+     * @param self self reference
+     * @return the value of the Float64Array property
+     */
+    @Getter(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
+    public static Object getFloat64Array(final Object self) {
+        final Global global = Global.instanceFrom(self);
+        if (global.float64Array == LAZY_SENTINEL) {
+            global.float64Array = global.getBuiltinFloat64Array();
+        }
+        return global.float64Array;
+    }
+
+    /**
+     * Setter for the Float64Array property.
+     *
+     * @param self self reference
+     * @param value value of the Float64Array property
+     */
+    @Setter(name = "Float64Array", attributes = Attribute.NOT_ENUMERABLE)
+    public static void setFloat64Array(final Object self, final Object value) {
+        final Global global = Global.instanceFrom(self);
+        global.float64Array = value;
+    }
+
+    private volatile Object float64Array;
 
     /** Nashorn extension: Java access - global.Packages */
     @Property(name = "Packages", attributes = Attribute.NOT_ENUMERABLE)
@@ -331,31 +770,89 @@
     @Property(attributes = Attribute.NOT_ENUMERABLE)
     public volatile Object org;
 
-    /** Nashorn extension: Java access - global.javaImporter */
-    @Property(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
-    public volatile Object javaImporter;
+    /**
+     * Getter for the Nashorn extension: Java access - global.javaImporter.
+     *
+     * @param self self reference
+     * @return the value of the JavaImporter property
+     */
+    @Getter(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
+    public static Object getJavaImporter(final Object self) {
+        final Global global = Global.instanceFrom(self);
+        if (global.javaImporter == LAZY_SENTINEL) {
+            global.javaImporter = global.getBuiltinJavaImporter();
+        }
+        return global.javaImporter;
+    }
 
-    /** Nashorn extension: global.Java Object constructor. */
-    @Property(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
-    public volatile Object javaApi;
+    /**
+     * Setter for the Nashorn extension: Java access - global.javaImporter.
+     *
+     * @param self self reference
+     * @param value value of the JavaImporter property
+     */
+    @Setter(name = "JavaImporter", attributes = Attribute.NOT_ENUMERABLE)
+    public static void setJavaImporter(final Object self, final Object value) {
+        final Global global = Global.instanceFrom(self);
+        global.javaImporter = value;
+    }
+
+    private volatile Object javaImporter;
+
+    /**
+     * Getter for the Nashorn extension: global.Java property.
+     *
+     * @param self self reference
+     * @return the value of the Java property
+     */
+    @Getter(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
+    public static Object getJavaApi(final Object self) {
+        final Global global = Global.instanceFrom(self);
+        if (global.javaApi == LAZY_SENTINEL) {
+            global.javaApi = global.getBuiltinJavaApi();
+        }
+        return global.javaApi;
+    }
+
+    /**
+     * Setter for the Nashorn extension: global.Java property.
+     *
+     * @param self self reference
+     * @param value value of the Java property
+     */
+    @Setter(name = "Java", attributes = Attribute.NOT_ENUMERABLE)
+    public static void setJavaApi(final Object self, final Object value) {
+        final Global global = Global.instanceFrom(self);
+        global.javaApi = value;
+    }
+
+    private volatile Object javaApi;
 
     /** Nashorn extension: current script's file name */
     @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public final Object __FILE__ = LOCATION_PROPERTY_PLACEHOLDER;
+    public static final Object __FILE__ = LAZY_SENTINEL;
 
     /** Nashorn extension: current script's directory */
     @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public final Object __DIR__ = LOCATION_PROPERTY_PLACEHOLDER;
+    public static final Object __DIR__ = LAZY_SENTINEL;
 
     /** Nashorn extension: current source line number being executed */
     @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER;
+    public static final Object __LINE__ = LAZY_SENTINEL;
+
+    private volatile NativeDate DEFAULT_DATE;
 
     /** Used as Date.prototype's default value */
-    public NativeDate   DEFAULT_DATE;
+    NativeDate getDefaultDate() {
+        return DEFAULT_DATE;
+    }
+
+    private volatile NativeRegExp DEFAULT_REGEXP;
 
     /** Used as RegExp.prototype's default value */
-    public NativeRegExp DEFAULT_REGEXP;
+    NativeRegExp getDefaultRegExp() {
+        return DEFAULT_REGEXP;
+    }
 
     /*
      * Built-in constructor objects: Even if user changes dynamic values of
@@ -409,9 +906,6 @@
      */
     private ScriptFunction typeErrorThrower;
 
-    // Flag to indicate that a split method issued a return statement
-    private int splitState = -1;
-
     // Used to store the last RegExp result to support deprecated RegExp constructor properties
     private RegExpResult lastRegExpResult;
 
@@ -422,7 +916,7 @@
     private static final MethodHandle LOAD                 = findOwnMH_S("load",                Object.class, Object.class, Object.class);
     private static final MethodHandle LOAD_WITH_NEW_GLOBAL = findOwnMH_S("loadWithNewGlobal",   Object.class, Object.class, Object[].class);
     private static final MethodHandle EXIT                 = findOwnMH_S("exit",                Object.class, Object.class, Object.class);
-    private static final MethodHandle LEXICAL_SCOPE_FILTER = findOwnMH_S("lexicalScopeFilter", Object.class, Object.class);
+    private static final MethodHandle LEXICAL_SCOPE_FILTER = findOwnMH_S("lexicalScopeFilter",  Object.class, Object.class);
 
     // initialized by nasgen
     private static PropertyMap $nasgenmap$;
@@ -431,7 +925,7 @@
     private final Context context;
 
     // current ScriptContext to use - can be null.
-    private ScriptContext scontext;
+    private ThreadLocal<ScriptContext> scontext;
     // current ScriptEngine associated - can be null.
     private ScriptEngine engine;
 
@@ -443,10 +937,25 @@
 
     /**
      * Set the current script context
-     * @param scontext script context
+     * @param ctxt script context
      */
-    public void setScriptContext(final ScriptContext scontext) {
-        this.scontext = scontext;
+    public void setScriptContext(final ScriptContext ctxt) {
+        assert scontext != null;
+        scontext.set(ctxt);
+    }
+
+    /**
+     * Get the current script context
+     * @return current script context
+     */
+    public ScriptContext getScriptContext() {
+        assert scontext != null;
+        return scontext.get();
+    }
+
+    private ScriptContext currentContext() {
+        final ScriptContext sc = scontext != null? scontext.get() : null;
+        return (sc != null)? sc : (engine != null? engine.getContext() : null);
     }
 
     @Override
@@ -454,6 +963,11 @@
         return context;
     }
 
+    @Override
+    protected boolean useDualFields() {
+        return context.useDualFields();
+    }
+
     // performs initialization checks for Global constructor and returns the
     // PropertyMap, if everything is fine.
     private static PropertyMap checkAndGetMap(final Context context) {
@@ -463,8 +977,7 @@
             sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
         }
 
-        // null check on context
-        context.getClass();
+        Objects.requireNonNull(context);
 
         return $nasgenmap$;
     }
@@ -477,7 +990,6 @@
     public Global(final Context context) {
         super(checkAndGetMap(context));
         this.context = context;
-        this.setIsScope();
         this.lexicalScope = context.getEnv()._es6 ? new LexicalScope(this) : null;
     }
 
@@ -487,9 +999,7 @@
      * @return the global singleton
      */
     public static Global instance() {
-        final Global global = Context.getGlobal();
-        global.getClass(); // null check
-        return global;
+        return Objects.requireNonNull(Context.getGlobal());
     }
 
     private static Global instanceFrom(final Object self) {
@@ -554,17 +1064,19 @@
      * as well as our extension builtin objects like "Java", "JSAdapter" as properties
      * of the global scope object.
      *
-     * @param engine ScriptEngine to initialize
+     * @param eng ScriptEngine to initialize
      */
-    @SuppressWarnings("hiding")
-    public void initBuiltinObjects(final ScriptEngine engine) {
+    public void initBuiltinObjects(final ScriptEngine eng) {
         if (this.builtinObject != null) {
             // already initialized, just return
             return;
         }
 
-        this.engine = engine;
-        init(engine);
+        this.engine = eng;
+        if (this.engine != null) {
+            this.scontext = new ThreadLocal<>();
+        }
+        init(eng);
     }
 
     /**
@@ -578,16 +1090,18 @@
             return new NativeBoolean((Boolean)obj, this);
         } else if (obj instanceof Number) {
             return new NativeNumber(((Number)obj).doubleValue(), this);
-        } else if (obj instanceof String || obj instanceof ConsString) {
+        } else if (isString(obj)) {
             return new NativeString((CharSequence)obj, this);
         } else if (obj instanceof Object[]) { // extension
-            return new NativeArray((Object[])obj);
+            return new NativeArray(ArrayData.allocate((Object[])obj), this);
         } else if (obj instanceof double[]) { // extension
-            return new NativeArray((double[])obj);
+            return new NativeArray(ArrayData.allocate((double[])obj), this);
         } else if (obj instanceof long[]) {
-            return new NativeArray((long[])obj);
+            return new NativeArray(ArrayData.allocate((long[])obj), this);
         } else if (obj instanceof int[]) {
-            return new NativeArray((int[])obj);
+            return new NativeArray(ArrayData.allocate((int[]) obj), this);
+        } else if (obj instanceof ArrayData) {
+            return new NativeArray((ArrayData) obj, this);
         } else {
             // FIXME: more special cases? Map? List?
             return obj;
@@ -603,7 +1117,7 @@
      * @return guarded invocation
      */
     public static GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
-        if (self instanceof String || self instanceof ConsString) {
+        if (isString(self)) {
             return NativeString.lookupPrimitive(request, self);
         } else if (self instanceof Number) {
             return NativeNumber.lookupPrimitive(request, self);
@@ -620,7 +1134,7 @@
      * @return method handle to create wrapper objects for primitive receiver
      */
     public static MethodHandle getPrimitiveWrapFilter(final Object self) {
-        if (self instanceof String || self instanceof ConsString) {
+        if (isString(self)) {
             return NativeString.WRAPFILTER;
         } else if (self instanceof Number) {
             return NativeNumber.WRAPFILTER;
@@ -637,7 +1151,7 @@
      * @return the new ScriptObject
      */
     public ScriptObject newObject() {
-        return new JO(getObjectPrototype(), JO.getInitialMap());
+        return useDualFields() ? new JD(getObjectPrototype()) : new JO(getObjectPrototype());
     }
 
     /**
@@ -890,7 +1404,7 @@
      */
     public static Object __noSuchProperty__(final Object self, final Object name) {
         final Global global = Global.instance();
-        final ScriptContext sctxt = global.scontext;
+        final ScriptContext sctxt = global.currentContext();
         final String nameStr = name.toString();
 
         if (sctxt != null) {
@@ -929,7 +1443,7 @@
      * @return the result of eval
      */
     public static Object eval(final Object self, final Object str) {
-        return directEval(self, str, UNDEFINED, UNDEFINED, false);
+        return directEval(self, str, Global.instanceFrom(self), UNDEFINED, false);
     }
 
     /**
@@ -939,18 +1453,18 @@
      * @param str      Evaluated code
      * @param callThis "this" to be passed to the evaluated code
      * @param location location of the eval call
-     * @param strict   is eval called a strict mode code?
+     * @param strict   is eval called from a strict mode code?
      *
      * @return the return value of the eval
      *
      * 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 boolean strict) {
-        if (!(str instanceof String || str instanceof ConsString)) {
+        if (!isString(str)) {
             return str;
         }
         final Global global = Global.instanceFrom(self);
-        final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
+        final ScriptObject scope = self instanceof ScriptObject && ((ScriptObject)self).isScope() ? (ScriptObject)self : global;
 
         return global.getContext().eval(scope, str.toString(), callThis, location, strict, true);
     }
@@ -980,26 +1494,53 @@
     }
 
     /**
-     * Global load implementation - Nashorn extension
+     * Global load implementation - Nashorn extension.
      *
-     * @param self    scope
-     * @param source  source to load
+     * <p>
+     * load builtin loads the given script. Script source can be a URL or a File
+     * or a script object with name and script properties. Evaluated code gets
+     * global object "this" and uses global object as scope for evaluation.
+     * </p>
+     * <p>
+     * If self is undefined or null or global, then global object is used
+     * as scope as well as "this" for the evaluated code. If self is any other
+     * object, then it is indirect load call. With indirect load call, the
+     * properties of scope are available to evaluated script as variables. Also,
+     * global scope properties are accessible. Any var, function definition in
+     * evaluated script goes into an object that is not accessible to user scripts.
+     * </p>
+     * Thus the indirect load call is equivalent to the following:
+     * <pre>
+     * <code>
+     * (function (scope, source) {
+     *    with(scope) {
+     *        eval(&lt;script_from_source&gt;);
+     *    }
+     * })(self, source);
+     * </code>
+     * </pre>
      *
-     * @return result of load (undefined)
+     * @param self    scope to use for the script evaluation
+     * @param source  script source
+     *
+     * @return result of load (may be undefined)
      *
      * @throws IOException if source could not be read
      */
     public static Object load(final Object self, final Object source) throws IOException {
         final Global global = Global.instanceFrom(self);
-        final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
-        return global.getContext().load(scope, source);
+        return global.getContext().load(self, source);
     }
 
     /**
-     * Global loadWithNewGlobal implementation - Nashorn extension
+     * Global loadWithNewGlobal implementation - Nashorn extension.
      *
-     * @param self scope
-     * @param args from plus (optional) arguments to be passed to the loaded script
+     * loadWithNewGlobal builtin loads the given script from a URL or a File
+     * or a script object with name and script properties. Evaluated code gets
+     * new global object "this" and uses that new global object as scope for evaluation.
+     *
+     * @param self self This value is ignored by this function
+     * @param args optional arguments to be passed to the loaded script
      *
      * @return result of load (may be undefined)
      *
@@ -1029,12 +1570,21 @@
     }
 
     // builtin prototype accessors
-    ScriptObject getFunctionPrototype() {
-        return ScriptFunction.getPrototype(builtinFunction);
+
+    /**
+     * Get the builtin Object prototype.
+     * @return the object prototype.
+     */
+    public ScriptObject getObjectPrototype() {
+        return ScriptFunction.getPrototype(builtinObject);
     }
 
-    ScriptObject getObjectPrototype() {
-        return ScriptFunction.getPrototype(builtinObject);
+    /**
+     * Get the builtin Function prototype.
+     * @return the Function.prototype.
+     */
+    public ScriptObject getFunctionPrototype() {
+        return ScriptFunction.getPrototype(builtinFunction);
     }
 
     ScriptObject getArrayPrototype() {
@@ -1050,11 +1600,11 @@
     }
 
     ScriptObject getDatePrototype() {
-        return ScriptFunction.getPrototype(builtinDate);
+        return ScriptFunction.getPrototype(getBuiltinDate());
     }
 
     ScriptObject getRegExpPrototype() {
-        return ScriptFunction.getPrototype(builtinRegExp);
+        return ScriptFunction.getPrototype(getBuiltinRegExp());
     }
 
     ScriptObject getStringPrototype() {
@@ -1066,11 +1616,11 @@
     }
 
     ScriptObject getEvalErrorPrototype() {
-        return ScriptFunction.getPrototype(builtinEvalError);
+        return ScriptFunction.getPrototype(getBuiltinEvalError());
     }
 
     ScriptObject getRangeErrorPrototype() {
-        return ScriptFunction.getPrototype(builtinRangeError);
+        return ScriptFunction.getPrototype(getBuiltinRangeError());
     }
 
     ScriptObject getReferenceErrorPrototype() {
@@ -1086,133 +1636,162 @@
     }
 
     ScriptObject getURIErrorPrototype() {
-        return ScriptFunction.getPrototype(builtinURIError);
+        return ScriptFunction.getPrototype(getBuiltinURIError());
     }
 
     ScriptObject getJavaImporterPrototype() {
-        return ScriptFunction.getPrototype(builtinJavaImporter);
+        return ScriptFunction.getPrototype(getBuiltinJavaImporter());
     }
 
     ScriptObject getJSAdapterPrototype() {
-        return ScriptFunction.getPrototype(builtinJSAdapter);
+        return ScriptFunction.getPrototype(getBuiltinJSAdapter());
+    }
+
+    private synchronized ScriptFunction getBuiltinArrayBuffer() {
+        if (this.builtinArrayBuffer == null) {
+            this.builtinArrayBuffer = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class);
+        }
+        return this.builtinArrayBuffer;
     }
 
     ScriptObject getArrayBufferPrototype() {
-        return ScriptFunction.getPrototype(builtinArrayBuffer);
+        return ScriptFunction.getPrototype(getBuiltinArrayBuffer());
+    }
+
+    private synchronized ScriptFunction getBuiltinDataView() {
+        if (this.builtinDataView == null) {
+            this.builtinDataView = initConstructorAndSwitchPoint("DataView", ScriptFunction.class);
+        }
+        return this.builtinDataView;
     }
 
     ScriptObject getDataViewPrototype() {
-        return ScriptFunction.getPrototype(builtinDataView);
+        return ScriptFunction.getPrototype(getBuiltinDataView());
+    }
+
+    private synchronized ScriptFunction getBuiltinInt8Array() {
+        if (this.builtinInt8Array == null) {
+            this.builtinInt8Array = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class);
+        }
+        return this.builtinInt8Array;
     }
 
     ScriptObject getInt8ArrayPrototype() {
-        return ScriptFunction.getPrototype(builtinInt8Array);
+        return ScriptFunction.getPrototype(getBuiltinInt8Array());
+    }
+
+    private synchronized ScriptFunction getBuiltinUint8Array() {
+        if (this.builtinUint8Array == null) {
+            this.builtinUint8Array = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class);
+        }
+        return this.builtinUint8Array;
     }
 
     ScriptObject getUint8ArrayPrototype() {
-        return ScriptFunction.getPrototype(builtinUint8Array);
+        return ScriptFunction.getPrototype(getBuiltinUint8Array());
+    }
+
+    private synchronized ScriptFunction getBuiltinUint8ClampedArray() {
+        if (this.builtinUint8ClampedArray == null) {
+            this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class);
+        }
+        return this.builtinUint8ClampedArray;
     }
 
     ScriptObject getUint8ClampedArrayPrototype() {
-        return ScriptFunction.getPrototype(builtinUint8ClampedArray);
+        return ScriptFunction.getPrototype(getBuiltinUint8ClampedArray());
+    }
+
+    private synchronized ScriptFunction getBuiltinInt16Array() {
+        if (this.builtinInt16Array == null) {
+            this.builtinInt16Array = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class);
+        }
+        return this.builtinInt16Array;
     }
 
     ScriptObject getInt16ArrayPrototype() {
-        return ScriptFunction.getPrototype(builtinInt16Array);
+        return ScriptFunction.getPrototype(getBuiltinInt16Array());
+    }
+
+    private synchronized ScriptFunction getBuiltinUint16Array() {
+        if (this.builtinUint16Array == null) {
+            this.builtinUint16Array = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class);
+        }
+        return this.builtinUint16Array;
     }
 
     ScriptObject getUint16ArrayPrototype() {
-        return ScriptFunction.getPrototype(builtinUint16Array);
+        return ScriptFunction.getPrototype(getBuiltinUint16Array());
+    }
+
+    private synchronized ScriptFunction getBuiltinInt32Array() {
+        if (this.builtinInt32Array == null) {
+            this.builtinInt32Array = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class);
+        }
+        return this.builtinInt32Array;
     }
 
     ScriptObject getInt32ArrayPrototype() {
-        return ScriptFunction.getPrototype(builtinInt32Array);
+        return ScriptFunction.getPrototype(getBuiltinInt32Array());
+    }
+
+    private synchronized ScriptFunction getBuiltinUint32Array() {
+        if (this.builtinUint32Array == null) {
+            this.builtinUint32Array = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class);
+        }
+        return this.builtinUint32Array;
     }
 
     ScriptObject getUint32ArrayPrototype() {
-        return ScriptFunction.getPrototype(builtinUint32Array);
+        return ScriptFunction.getPrototype(getBuiltinUint32Array());
+    }
+
+    private synchronized ScriptFunction getBuiltinFloat32Array() {
+        if (this.builtinFloat32Array == null) {
+            this.builtinFloat32Array = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class);
+        }
+        return this.builtinFloat32Array;
     }
 
     ScriptObject getFloat32ArrayPrototype() {
-        return ScriptFunction.getPrototype(builtinFloat32Array);
+        return ScriptFunction.getPrototype(getBuiltinFloat32Array());
+    }
+
+    private synchronized ScriptFunction getBuiltinFloat64Array() {
+        if (this.builtinFloat64Array == null) {
+            this.builtinFloat64Array = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class);
+        }
+        return this.builtinFloat64Array;
     }
 
     ScriptObject getFloat64ArrayPrototype() {
-        return ScriptFunction.getPrototype(builtinFloat64Array);
+        return ScriptFunction.getPrototype(getBuiltinFloat64Array());
     }
 
-    private ScriptFunction getBuiltinArray() {
-        return builtinArray;
-    }
-
-    ScriptFunction getTypeErrorThrower() {
+    /**
+     * Return the function that throws TypeError unconditionally. Used as "poison" methods for certain Function properties.
+     *
+     * @return the TypeError throwing function
+     */
+    public ScriptFunction getTypeErrorThrower() {
         return typeErrorThrower;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin array has not been overridden
-     */
-    public static boolean isBuiltinArray() {
-        final Global instance = Global.instance();
-        return instance.array == instance.getBuiltinArray();
+    private synchronized ScriptFunction getBuiltinDate() {
+        if (this.builtinDate == null) {
+            this.builtinDate = initConstructorAndSwitchPoint("Date", ScriptFunction.class);
+            final ScriptObject dateProto = ScriptFunction.getPrototype(builtinDate);
+            // initialize default date
+            this.DEFAULT_DATE = new NativeDate(NaN, dateProto);
+        }
+        return this.builtinDate;
     }
 
-    private ScriptFunction getBuiltinBoolean() {
-        return builtinBoolean;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin boolean has not been overridden
-     */
-    public static boolean isBuiltinBoolean() {
-        final Global instance = Global.instance();
-        return instance._boolean == instance.getBuiltinBoolean();
-    }
-
-    private ScriptFunction getBuiltinDate() {
-        return builtinDate;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin date has not been overridden
-     */
-    public static boolean isBuiltinDate() {
-        final Global instance = Global.instance();
-        return instance.date == instance.getBuiltinDate();
-    }
-
-    private ScriptFunction getBuiltinError() {
-        return builtinError;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin error has not been overridden
-     */
-    public static boolean isBuiltinError() {
-        final Global instance = Global.instance();
-        return instance.error == instance.getBuiltinError();
-    }
-
-    private ScriptFunction getBuiltinEvalError() {
-        return builtinEvalError;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin eval error has not been overridden
-     */
-    public static boolean isBuiltinEvalError() {
-        final Global instance = Global.instance();
-        return instance.evalError == instance.getBuiltinEvalError();
+    private synchronized ScriptFunction getBuiltinEvalError() {
+        if (this.builtinEvalError == null) {
+            this.builtinEvalError = initErrorSubtype("EvalError", getErrorPrototype());
+        }
+        return this.builtinEvalError;
     }
 
     private ScriptFunction getBuiltinFunction() {
@@ -1220,16 +1799,6 @@
     }
 
     /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin function has not been overridden
-     */
-    public static boolean isBuiltinFunction() {
-        final Global instance = Global.instance();
-        return instance.function == instance.getBuiltinFunction();
-    }
-
-    /**
      * Get the switchpoint used to check property changes for Function.prototype.apply
      * @return the switchpoint guarding apply (same as guarding call, and everything else in function)
      */
@@ -1263,228 +1832,59 @@
         return isBuiltinFunctionProperty("call");
     }
 
-    private ScriptFunction getBuiltinJSAdapter() {
+    private synchronized ScriptFunction getBuiltinJSAdapter() {
+        if (this.builtinJSAdapter == null) {
+            this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class);
+        }
         return builtinJSAdapter;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin JSAdapter has not been overridden
-     */
-    public static boolean isBuiltinJSAdapter() {
-        final Global instance = Global.instance();
-        return instance.jsadapter == instance.getBuiltinJSAdapter();
+    private synchronized ScriptObject getBuiltinJSON() {
+        if (this.builtinJSON == null) {
+            this.builtinJSON = initConstructorAndSwitchPoint("JSON", ScriptObject.class);
+        }
+        return this.builtinJSON;
     }
 
-    private ScriptObject getBuiltinJSON() {
-        return builtinJSON;
+    private synchronized ScriptFunction getBuiltinJavaImporter() {
+        if (this.builtinJavaImporter == null) {
+            this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
+        }
+        return this.builtinJavaImporter;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin JSON has has not been overridden
-     */
-    public static boolean isBuiltinJSON() {
-        final Global instance = Global.instance();
-        return instance.json == instance.getBuiltinJSON();
+    private synchronized ScriptObject getBuiltinJavaApi() {
+        if (this.builtinJavaApi == null) {
+            this.builtinJavaApi = initConstructor("Java", ScriptObject.class);
+        }
+        return this.builtinJavaApi;
     }
 
-    private ScriptObject getBuiltinJava() {
-        return builtinJava;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin Java has not been overridden
-     */
-    public static boolean isBuiltinJava() {
-        final Global instance = Global.instance();
-        return instance.java == instance.getBuiltinJava();
-    }
-
-    private ScriptObject getBuiltinJavax() {
-        return builtinJavax;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin Javax has not been overridden
-     */
-    public static boolean isBuiltinJavax() {
-        final Global instance = Global.instance();
-        return instance.javax == instance.getBuiltinJavax();
-    }
-
-    private ScriptObject getBuiltinJavaImporter() {
-        return builtinJavaImporter;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin Java importer has not been overridden
-     */
-    public static boolean isBuiltinJavaImporter() {
-        final Global instance = Global.instance();
-        return instance.javaImporter == instance.getBuiltinJavaImporter();
-    }
-
-    private ScriptObject getBuiltinMath() {
-        return builtinMath;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin math has not been overridden
-     */
-    public static boolean isBuiltinMath() {
-        final Global instance = Global.instance();
-        return instance.math == instance.getBuiltinMath();
-    }
-
-    private ScriptFunction getBuiltinNumber() {
-        return builtinNumber;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin number has not been overridden
-     */
-    public static boolean isBuiltinNumber() {
-        final Global instance = Global.instance();
-        return instance.number == instance.getBuiltinNumber();
-    }
-
-    private ScriptFunction getBuiltinObject() {
-        return builtinObject;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin object has not been overridden
-     */
-    public static boolean isBuiltinObject() {
-        final Global instance = Global.instance();
-        return instance.object == instance.getBuiltinObject();
-    }
-
-    private ScriptObject getBuiltinPackages() {
-        return builtinPackages;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin package has not been overridden
-     */
-    public static boolean isBuiltinPackages() {
-        final Global instance = Global.instance();
-        return instance.packages == instance.getBuiltinPackages();
-    }
-
-    private ScriptFunction getBuiltinRangeError() {
+    private synchronized ScriptFunction getBuiltinRangeError() {
+        if (this.builtinRangeError == null) {
+            this.builtinRangeError = initErrorSubtype("RangeError", getErrorPrototype());
+        }
         return builtinRangeError;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin range error has not been overridden
-     */
-    public static boolean isBuiltinRangeError() {
-        final Global instance = Global.instance();
-        return instance.rangeError == instance.getBuiltinRangeError();
-    }
-
-    private ScriptFunction getBuiltinReferenceError() {
-        return builtinReferenceError;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin reference error has not been overridden
-     */
-    public static boolean isBuiltinReferenceError() {
-        final Global instance = Global.instance();
-        return instance.referenceError == instance.getBuiltinReferenceError();
-    }
-
-    private ScriptFunction getBuiltinRegExp() {
+    private synchronized ScriptFunction getBuiltinRegExp() {
+        if (this.builtinRegExp == null) {
+            this.builtinRegExp = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class);
+            final ScriptObject regExpProto = ScriptFunction.getPrototype(builtinRegExp);
+            // initialize default regexp object
+            this.DEFAULT_REGEXP = new NativeRegExp("(?:)", "", this, regExpProto);
+            // RegExp.prototype should behave like a RegExp object. So copy the
+            // properties.
+            regExpProto.addBoundProperties(DEFAULT_REGEXP);
+        }
         return builtinRegExp;
     }
 
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin regexp has not been overridden
-     */
-    public static boolean isBuiltinRegExp() {
-        final Global instance = Global.instance();
-        return instance.regexp == instance.getBuiltinRegExp();
-    }
-
-    private ScriptFunction getBuiltinString() {
-        return builtinString;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin Java has not been overridden
-     */
-    public static boolean isBuiltinString() {
-        final Global instance = Global.instance();
-        return instance.string == instance.getBuiltinString();
-    }
-
-    private ScriptFunction getBuiltinSyntaxError() {
-        return builtinSyntaxError;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin syntax error has not been overridden
-     */
-    public static boolean isBuiltinSyntaxError() {
-        final Global instance = Global.instance();
-        return instance.syntaxError == instance.getBuiltinSyntaxError();
-    }
-
-    private ScriptFunction getBuiltinTypeError() {
-        return builtinTypeError;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin type error has not been overridden
-     */
-    public static boolean isBuiltinTypeError() {
-        final Global instance = Global.instance();
-        return instance.typeError == instance.getBuiltinTypeError();
-    }
-
-    private ScriptFunction getBuiltinURIError() {
-        return builtinURIError;
-    }
-
-    /**
-     * Called from compiled script code to test if builtin has been overridden
-     *
-     * @return true if builtin URI error has not been overridden
-     */
-    public static boolean isBuiltinURIError() {
-        final Global instance = Global.instance();
-        return instance.uriError == instance.getBuiltinURIError();
+    private synchronized ScriptFunction getBuiltinURIError() {
+        if (this.builtinURIError == null) {
+            this.builtinURIError = initErrorSubtype("URIError", getErrorPrototype());
+        }
+        return this.builtinURIError;
     }
 
     @Override
@@ -1625,7 +2025,7 @@
      * @return true if the value is a placeholder, false otherwise.
      */
     public static boolean isLocationPropertyPlaceholder(final Object placeholder) {
-        return placeholder == LOCATION_PROPERTY_PLACEHOLDER;
+        return placeholder == LAZY_SENTINEL;
     }
 
     /**
@@ -1688,26 +2088,6 @@
     }
 
     /**
-     * Get the current split state.
-     *
-     * @return current split state
-     */
-    @Override
-    public int getSplitState() {
-        return splitState;
-    }
-
-    /**
-     * Set the current split state.
-     *
-     * @param state current split state
-     */
-    @Override
-    public void setSplitState(final int state) {
-        splitState = state;
-    }
-
-    /**
      * Return the ES6 global scope for lexically declared bindings.
      * @return the ES6 lexical global scope.
      */
@@ -1719,13 +2099,13 @@
     @Override
     public void addBoundProperties(final ScriptObject source, final jdk.nashorn.internal.runtime.Property[] properties) {
         PropertyMap ownMap = getMap();
-        LexicalScope lexicalScope = null;
+        LexicalScope lexScope = null;
         PropertyMap lexicalMap = null;
         boolean hasLexicalDefinitions = false;
 
         if (context.getEnv()._es6) {
-            lexicalScope = (LexicalScope) getLexicalScope();
-            lexicalMap = lexicalScope.getMap();
+            lexScope = (LexicalScope) getLexicalScope();
+            lexicalMap = lexScope.getMap();
 
             for (final jdk.nashorn.internal.runtime.Property property : properties) {
                 if (property.isLexicalBinding()) {
@@ -1743,24 +2123,26 @@
             }
         }
 
+        final boolean extensible = isExtensible();
         for (final jdk.nashorn.internal.runtime.Property property : properties) {
             if (property.isLexicalBinding()) {
-                assert lexicalScope != null;
-                lexicalMap = lexicalScope.addBoundProperty(lexicalMap, source, property);
+                assert lexScope != null;
+                lexicalMap = lexScope.addBoundProperty(lexicalMap, source, property, true);
 
                 if (ownMap.findProperty(property.getKey()) != null) {
                     // If property exists in the global object invalidate any global constant call sites.
                     invalidateGlobalConstant(property.getKey());
                 }
             } else {
-                ownMap = addBoundProperty(ownMap, source, property);
+                ownMap = addBoundProperty(ownMap, source, property, extensible);
             }
         }
 
         setMap(ownMap);
 
         if (hasLexicalDefinitions) {
-            lexicalScope.setMap(lexicalMap);
+            assert lexScope != null;
+            lexScope.setMap(lexicalMap);
             invalidateLexicalSwitchPoint();
         }
     }
@@ -1780,7 +2162,7 @@
 
         // We want to avoid adding our generic lexical scope switchpoint to global constant invocations,
         // because those are invalidated per-key in the addBoundProperties method above.
-        // We therefor check if the invocation does already have a switchpoint and the property is non-inherited,
+        // We therefore check if the invocation does already have a switchpoint and the property is non-inherited,
         // assuming this only applies to global constants. If other non-inherited properties will
         // start using switchpoints some time in the future we'll have to revisit this.
         if (isScope && context.getEnv()._es6 && (invocation.getSwitchPoints() == null || !hasOwnProperty(name))) {
@@ -1791,6 +2173,17 @@
     }
 
     @Override
+    protected FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) {
+        if (lexicalScope != null && start != this && start.isScope()) {
+            final FindProperty find = lexicalScope.findProperty(key, false);
+            if (find != null) {
+                return find;
+            }
+        }
+        return super.findProperty(key, deep, start);
+    }
+
+    @Override
     public GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
         final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
 
@@ -1810,6 +2203,17 @@
         return invocation;
     }
 
+    /**
+     * Adds jjs shell interactive mode builtin functions to global scope.
+     */
+    public void addShellBuiltins() {
+        Object value = ScriptFunction.createBuiltin("input", ShellFunctions.INPUT);
+        addOwnProperty("input", Attribute.NOT_ENUMERABLE, value);
+
+        value = ScriptFunction.createBuiltin("evalinput", ShellFunctions.EVALINPUT);
+        addOwnProperty("evalinput", Attribute.NOT_ENUMERABLE, value);
+    }
+
     private synchronized SwitchPoint getLexicalScopeSwitchPoint() {
         SwitchPoint switchPoint = lexicalScopeSwitchPoint;
         if (switchPoint == null || switchPoint.hasBeenInvalidated()) {
@@ -1841,7 +2245,7 @@
     }
 
     @SuppressWarnings("hiding")
-    private void init(final ScriptEngine engine) {
+    private void init(final ScriptEngine eng) {
         assert Context.getGlobal() == this : "this global is not set as current";
 
         final ScriptEnvironment env = getContext().getEnv();
@@ -1853,46 +2257,42 @@
         this.setInitialProto(getObjectPrototype());
 
         // initialize global function properties
-        this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
+        this.eval = this.builtinEval = ScriptFunction.createBuiltin("eval", EVAL);
 
-        this.parseInt = ScriptFunctionImpl.makeFunction("parseInt",   GlobalFunctions.PARSEINT,
+        this.parseInt = ScriptFunction.createBuiltin("parseInt",   GlobalFunctions.PARSEINT,
                     new Specialization[] {
                     new Specialization(GlobalFunctions.PARSEINT_Z),
                     new Specialization(GlobalFunctions.PARSEINT_I),
                     new Specialization(GlobalFunctions.PARSEINT_J),
                     new Specialization(GlobalFunctions.PARSEINT_OI),
                     new Specialization(GlobalFunctions.PARSEINT_O) });
-        this.parseFloat = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
-        this.isNaN = ScriptFunctionImpl.makeFunction("isNaN",   GlobalFunctions.IS_NAN,
+        this.parseFloat = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT);
+        this.isNaN = ScriptFunction.createBuiltin("isNaN",   GlobalFunctions.IS_NAN,
                    new Specialization[] {
                         new Specialization(GlobalFunctions.IS_NAN_I),
                         new Specialization(GlobalFunctions.IS_NAN_J),
                         new Specialization(GlobalFunctions.IS_NAN_D) });
-        this.parseFloat         = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
-        this.isNaN              = ScriptFunctionImpl.makeFunction("isNaN",      GlobalFunctions.IS_NAN);
-        this.isFinite           = ScriptFunctionImpl.makeFunction("isFinite",   GlobalFunctions.IS_FINITE);
-        this.encodeURI          = ScriptFunctionImpl.makeFunction("encodeURI",  GlobalFunctions.ENCODE_URI);
-        this.encodeURIComponent = ScriptFunctionImpl.makeFunction("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
-        this.decodeURI          = ScriptFunctionImpl.makeFunction("decodeURI",  GlobalFunctions.DECODE_URI);
-        this.decodeURIComponent = ScriptFunctionImpl.makeFunction("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
-        this.escape             = ScriptFunctionImpl.makeFunction("escape",     GlobalFunctions.ESCAPE);
-        this.unescape           = ScriptFunctionImpl.makeFunction("unescape",   GlobalFunctions.UNESCAPE);
-        this.print              = ScriptFunctionImpl.makeFunction("print",      env._print_no_newline ? PRINT : PRINTLN);
-        this.load               = ScriptFunctionImpl.makeFunction("load",       LOAD);
-        this.loadWithNewGlobal  = ScriptFunctionImpl.makeFunction("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL);
-        this.exit               = ScriptFunctionImpl.makeFunction("exit",       EXIT);
-        this.quit               = ScriptFunctionImpl.makeFunction("quit",       EXIT);
+        this.parseFloat         = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT);
+        this.isNaN              = ScriptFunction.createBuiltin("isNaN",      GlobalFunctions.IS_NAN);
+        this.isFinite           = ScriptFunction.createBuiltin("isFinite",   GlobalFunctions.IS_FINITE);
+        this.encodeURI          = ScriptFunction.createBuiltin("encodeURI",  GlobalFunctions.ENCODE_URI);
+        this.encodeURIComponent = ScriptFunction.createBuiltin("encodeURIComponent", GlobalFunctions.ENCODE_URICOMPONENT);
+        this.decodeURI          = ScriptFunction.createBuiltin("decodeURI",  GlobalFunctions.DECODE_URI);
+        this.decodeURIComponent = ScriptFunction.createBuiltin("decodeURIComponent", GlobalFunctions.DECODE_URICOMPONENT);
+        this.escape             = ScriptFunction.createBuiltin("escape",     GlobalFunctions.ESCAPE);
+        this.unescape           = ScriptFunction.createBuiltin("unescape",   GlobalFunctions.UNESCAPE);
+        this.print              = ScriptFunction.createBuiltin("print",      env._print_no_newline ? PRINT : PRINTLN);
+        this.load               = ScriptFunction.createBuiltin("load",       LOAD);
+        this.loadWithNewGlobal  = ScriptFunction.createBuiltin("loadWithNewGlobal", LOAD_WITH_NEW_GLOBAL);
+        this.exit               = ScriptFunction.createBuiltin("exit",       EXIT);
+        this.quit               = ScriptFunction.createBuiltin("quit",       EXIT);
 
         // built-in constructors
         this.builtinArray     = initConstructorAndSwitchPoint("Array", ScriptFunction.class);
         this.builtinBoolean   = initConstructorAndSwitchPoint("Boolean", ScriptFunction.class);
-        this.builtinDate      = initConstructorAndSwitchPoint("Date", ScriptFunction.class);
-        this.builtinJSON      = initConstructorAndSwitchPoint("JSON", ScriptObject.class);
-        this.builtinJSAdapter = initConstructorAndSwitchPoint("JSAdapter", ScriptFunction.class);
-        this.builtinMath      = initConstructorAndSwitchPoint("Math", ScriptObject.class);
         this.builtinNumber    = initConstructorAndSwitchPoint("Number", ScriptFunction.class);
-        this.builtinRegExp    = initConstructorAndSwitchPoint("RegExp", ScriptFunction.class);
         this.builtinString    = initConstructorAndSwitchPoint("String", ScriptFunction.class);
+        this.builtinMath      = initConstructorAndSwitchPoint("Math", ScriptObject.class);
 
         // initialize String.prototype.length to 0
         // add String.prototype.length
@@ -1903,26 +2303,28 @@
         final ScriptObject arrayPrototype = getArrayPrototype();
         arrayPrototype.setIsArray();
 
-        this.DEFAULT_DATE = new NativeDate(Double.NaN, this);
-
-        // initialize default regexp object
-        this.DEFAULT_REGEXP = new NativeRegExp("(?:)", this);
-
-        // RegExp.prototype should behave like a RegExp object. So copy the
-        // properties.
-        final ScriptObject regExpProto = getRegExpPrototype();
-        regExpProto.addBoundProperties(DEFAULT_REGEXP);
-
         // Error stuff
         initErrorObjects();
 
         // java access
         if (! env._no_java) {
+            this.javaApi = LAZY_SENTINEL;
+            this.javaImporter = LAZY_SENTINEL;
             initJavaAccess();
         }
 
         if (! env._no_typed_arrays) {
-            initTypedArray();
+            this.arrayBuffer       = LAZY_SENTINEL;
+            this.dataView          = LAZY_SENTINEL;
+            this.int8Array         = LAZY_SENTINEL;
+            this.uint8Array        = LAZY_SENTINEL;
+            this.uint8ClampedArray = LAZY_SENTINEL;
+            this.int16Array        = LAZY_SENTINEL;
+            this.uint16Array       = LAZY_SENTINEL;
+            this.int32Array        = LAZY_SENTINEL;
+            this.uint32Array       = LAZY_SENTINEL;
+            this.float32Array      = LAZY_SENTINEL;
+            this.float64Array      = LAZY_SENTINEL;
         }
 
         if (env._scripting) {
@@ -1959,11 +2361,11 @@
             addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
         }
 
-        if (engine != null) {
+        if (eng != null) {
             // 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);
+            final ScriptFunction noSuchProp = ScriptFunction.createStrictBuiltin(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
             addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
         }
     }
@@ -1974,17 +2376,17 @@
         final ScriptObject errorProto = getErrorPrototype();
 
         // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
-        final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", NativeError.GET_STACK);
-        final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", NativeError.SET_STACK);
+        final ScriptFunction getStack = ScriptFunction.createBuiltin("getStack", NativeError.GET_STACK);
+        final ScriptFunction setStack = ScriptFunction.createBuiltin("setStack", NativeError.SET_STACK);
         errorProto.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
-        final ScriptFunction getLineNumber = ScriptFunctionImpl.makeFunction("getLineNumber", NativeError.GET_LINENUMBER);
-        final ScriptFunction setLineNumber = ScriptFunctionImpl.makeFunction("setLineNumber", NativeError.SET_LINENUMBER);
+        final ScriptFunction getLineNumber = ScriptFunction.createBuiltin("getLineNumber", NativeError.GET_LINENUMBER);
+        final ScriptFunction setLineNumber = ScriptFunction.createBuiltin("setLineNumber", NativeError.SET_LINENUMBER);
         errorProto.addOwnProperty("lineNumber", Attribute.NOT_ENUMERABLE, getLineNumber, setLineNumber);
-        final ScriptFunction getColumnNumber = ScriptFunctionImpl.makeFunction("getColumnNumber", NativeError.GET_COLUMNNUMBER);
-        final ScriptFunction setColumnNumber = ScriptFunctionImpl.makeFunction("setColumnNumber", NativeError.SET_COLUMNNUMBER);
+        final ScriptFunction getColumnNumber = ScriptFunction.createBuiltin("getColumnNumber", NativeError.GET_COLUMNNUMBER);
+        final ScriptFunction setColumnNumber = ScriptFunction.createBuiltin("setColumnNumber", NativeError.SET_COLUMNNUMBER);
         errorProto.addOwnProperty("columnNumber", Attribute.NOT_ENUMERABLE, getColumnNumber, setColumnNumber);
-        final ScriptFunction getFileName = ScriptFunctionImpl.makeFunction("getFileName", NativeError.GET_FILENAME);
-        final ScriptFunction setFileName = ScriptFunctionImpl.makeFunction("setFileName", NativeError.SET_FILENAME);
+        final ScriptFunction getFileName = ScriptFunction.createBuiltin("getFileName", NativeError.GET_FILENAME);
+        final ScriptFunction setFileName = ScriptFunction.createBuiltin("setFileName", NativeError.SET_FILENAME);
         errorProto.addOwnProperty("fileName", Attribute.NOT_ENUMERABLE, getFileName, setFileName);
 
         // ECMA 15.11.4.2 Error.prototype.name
@@ -1996,12 +2398,9 @@
 
         tagBuiltinProperties("Error", builtinError);
 
-        this.builtinEvalError = initErrorSubtype("EvalError", errorProto);
-        this.builtinRangeError = initErrorSubtype("RangeError", errorProto);
         this.builtinReferenceError = initErrorSubtype("ReferenceError", errorProto);
         this.builtinSyntaxError = initErrorSubtype("SyntaxError", errorProto);
         this.builtinTypeError = initErrorSubtype("TypeError", errorProto);
-        this.builtinURIError = initErrorSubtype("URIError", errorProto);
     }
 
     private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
@@ -2023,25 +2422,25 @@
         this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
         this.builtinJavax = new NativeJavaPackage("javax", objectProto);
         this.builtinOrg = new NativeJavaPackage("org", objectProto);
-        this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
-        this.builtinJavaApi = initConstructor("Java", ScriptObject.class);
     }
 
     private void initScripting(final ScriptEnvironment scriptEnv) {
-        Object value;
-        value = ScriptFunctionImpl.makeFunction("readLine", ScriptingFunctions.READLINE);
+        ScriptObject value;
+        value = ScriptFunction.createBuiltin("readLine", ScriptingFunctions.READLINE);
         addOwnProperty("readLine", Attribute.NOT_ENUMERABLE, value);
 
-        value = ScriptFunctionImpl.makeFunction("readFully", ScriptingFunctions.READFULLY);
+        value = ScriptFunction.createBuiltin("readFully", ScriptingFunctions.READFULLY);
         addOwnProperty("readFully", Attribute.NOT_ENUMERABLE, value);
 
         final String execName = ScriptingFunctions.EXEC_NAME;
-        value = ScriptFunctionImpl.makeFunction(execName, ScriptingFunctions.EXEC);
+        value = ScriptFunction.createBuiltin(execName, ScriptingFunctions.EXEC);
+        value.addOwnProperty(ScriptingFunctions.THROW_ON_ERROR_NAME, Attribute.NOT_ENUMERABLE, false);
+
         addOwnProperty(execName, Attribute.NOT_ENUMERABLE, value);
 
         // Nashorn extension: global.echo (scripting-mode-only)
         // alias for "print"
-        value = get("print");
+        value = (ScriptObject)get("print");
         addOwnProperty("echo", Attribute.NOT_ENUMERABLE, value);
 
         // Nashorn extension: global.$OPTIONS (scripting-mode-only)
@@ -2055,6 +2454,14 @@
             // Retrieve current state of ENV variables.
             final ScriptObject env = newObject();
             env.putAll(System.getenv(), scriptEnv._strict);
+
+            // Some platforms, e.g., Windows, do not define the PWD environment
+            // variable, so that the $ENV.PWD property needs to be explicitly
+            // set.
+            if (!env.containsKey(ScriptingFunctions.PWD_NAME)) {
+                env.put(ScriptingFunctions.PWD_NAME, System.getProperty("user.dir"), scriptEnv._strict);
+            }
+
             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env);
         } else {
             addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED);
@@ -2076,60 +2483,25 @@
         }
     }
 
-    private void initTypedArray() {
-        this.builtinArrayBuffer       = initConstructorAndSwitchPoint("ArrayBuffer", ScriptFunction.class);
-        this.builtinDataView          = initConstructorAndSwitchPoint("DataView", ScriptFunction.class);
-        this.builtinInt8Array         = initConstructorAndSwitchPoint("Int8Array", ScriptFunction.class);
-        this.builtinUint8Array        = initConstructorAndSwitchPoint("Uint8Array", ScriptFunction.class);
-        this.builtinUint8ClampedArray = initConstructorAndSwitchPoint("Uint8ClampedArray", ScriptFunction.class);
-        this.builtinInt16Array        = initConstructorAndSwitchPoint("Int16Array", ScriptFunction.class);
-        this.builtinUint16Array       = initConstructorAndSwitchPoint("Uint16Array", ScriptFunction.class);
-        this.builtinInt32Array        = initConstructorAndSwitchPoint("Int32Array", ScriptFunction.class);
-        this.builtinUint32Array       = initConstructorAndSwitchPoint("Uint32Array", ScriptFunction.class);
-        this.builtinFloat32Array      = initConstructorAndSwitchPoint("Float32Array", ScriptFunction.class);
-        this.builtinFloat64Array      = initConstructorAndSwitchPoint("Float64Array", ScriptFunction.class);
-
-    }
-
     private void copyBuiltins() {
         this.array             = this.builtinArray;
         this._boolean          = this.builtinBoolean;
-        this.date              = this.builtinDate;
         this.error             = this.builtinError;
-        this.evalError         = this.builtinEvalError;
         this.function          = this.builtinFunction;
-        this.jsadapter         = this.builtinJSAdapter;
-        this.json              = this.builtinJSON;
         this.com               = this.builtinCom;
         this.edu               = this.builtinEdu;
         this.java              = this.builtinJava;
         this.javafx            = this.builtinJavafx;
         this.javax             = this.builtinJavax;
         this.org               = this.builtinOrg;
-        this.javaImporter      = this.builtinJavaImporter;
-        this.javaApi           = this.builtinJavaApi;
         this.math              = this.builtinMath;
         this.number            = this.builtinNumber;
         this.object            = this.builtinObject;
         this.packages          = this.builtinPackages;
-        this.rangeError        = this.builtinRangeError;
         this.referenceError    = this.builtinReferenceError;
-        this.regexp            = this.builtinRegExp;
         this.string            = this.builtinString;
         this.syntaxError       = this.builtinSyntaxError;
         this.typeError         = this.builtinTypeError;
-        this.uriError          = this.builtinURIError;
-        this.arrayBuffer       = this.builtinArrayBuffer;
-        this.dataView          = this.builtinDataView;
-        this.int8Array         = this.builtinInt8Array;
-        this.uint8Array        = this.builtinUint8Array;
-        this.uint8ClampedArray = this.builtinUint8ClampedArray;
-        this.int16Array        = this.builtinInt16Array;
-        this.uint16Array       = this.builtinUint16Array;
-        this.int32Array        = this.builtinInt32Array;
-        this.uint32Array       = this.builtinUint32Array;
-        this.float32Array      = this.builtinFloat32Array;
-        this.float64Array      = this.builtinFloat64Array;
     }
 
     private void initDebug() {
@@ -2137,8 +2509,9 @@
     }
 
     private Object printImpl(final boolean newLine, final Object... objects) {
+        final ScriptContext sc = currentContext();
         @SuppressWarnings("resource")
-        final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut();
+        final PrintWriter out = sc != null? new PrintWriter(sc.getWriter()) : getContext().getEnv().getOut();
         final StringBuilder sb = new StringBuilder();
 
         for (final Object obj : objects) {
@@ -2243,7 +2616,7 @@
         this.builtinFunction = initConstructor("Function", ScriptFunction.class);
 
         // create global anonymous function
-        final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
+        final ScriptFunction anon = ScriptFunction.createAnonymous();
         // need to copy over members of Function.prototype to anon function
         anon.addBoundProperties(getFunctionPrototype());
 
@@ -2255,10 +2628,7 @@
         anon.deleteOwnProperty(anon.getMap().findProperty("prototype"));
 
         // use "getter" so that [[ThrowTypeError]] function's arity is 0 - as specified in step 10 of section 13.2.3
-        this.typeErrorThrower = new ScriptFunctionImpl("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER, null, null, 0);
-        typeErrorThrower.setPrototype(UNDEFINED);
-        // Non-constructor built-in functions do not have "prototype" property
-        typeErrorThrower.deleteOwnProperty(typeErrorThrower.getMap().findProperty("prototype"));
+        this.typeErrorThrower = ScriptFunction.createBuiltin("TypeErrorThrower", Lookup.TYPE_ERROR_THROWER_GETTER);
         typeErrorThrower.preventExtensions();
 
         // now initialize Object
@@ -2269,8 +2639,8 @@
 
         // ES6 draft compliant __proto__ property of Object.prototype
         // accessors on Object.prototype for "__proto__"
-        final ScriptFunction getProto = ScriptFunctionImpl.makeFunction("getProto", NativeObject.GET__PROTO__);
-        final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__);
+        final ScriptFunction getProto = ScriptFunction.createBuiltin("getProto", NativeObject.GET__PROTO__);
+        final ScriptFunction setProto = ScriptFunction.createBuiltin("setProto", NativeObject.SET__PROTO__);
         ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
 
         // Function valued properties of Function.prototype were not properly
@@ -2351,8 +2721,8 @@
      */
     private static class LexicalScope extends ScriptObject {
 
-        LexicalScope(final ScriptObject proto) {
-            super(proto, PropertyMap.newMap());
+        LexicalScope(final Global global) {
+            super(global, PropertyMap.newMap());
         }
 
         @Override
@@ -2366,9 +2736,9 @@
         }
 
         @Override
-        protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property) {
+        protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final jdk.nashorn.internal.runtime.Property property, final boolean extensible) {
             // We override this method just to make it callable by Global
-            return super.addBoundProperty(propMap, source, property);
+            return super.addBoundProperty(propMap, source, property, extensible);
         }
 
         private static GuardedInvocation filterInvocation(final GuardedInvocation invocation) {
diff --git a/src/jdk/nashorn/internal/objects/NativeArray.java b/src/jdk/nashorn/internal/objects/NativeArray.java
index 047d612..9d9790e 100644
--- a/src/jdk/nashorn/internal/objects/NativeArray.java
+++ b/src/jdk/nashorn/internal/objects/NativeArray.java
@@ -120,9 +120,6 @@
         this(ArrayData.allocate(array.length));
 
         ArrayData arrayData = this.getArray();
-        if (array.length > 0) {
-            arrayData.ensure(array.length - 1);
-        }
 
         for (int index = 0; index < array.length; index++) {
             final Object value = array[index];
@@ -275,7 +272,7 @@
         final PropertyDescriptor newLenDesc = desc;
 
         // Step 3c and 3d - get new length and convert to long
-        final long newLen = NativeArray.validLength(newLenDesc.getValue(), true);
+        final long newLen = NativeArray.validLength(newLenDesc.getValue());
 
         // Step 3e
         newLenDesc.setValue(newLen);
@@ -348,8 +345,8 @@
         final PropertyDescriptor oldLenDesc = (PropertyDescriptor) super.getOwnPropertyDescriptor("length");
 
         // Step 2
-        // get old length and convert to long
-        final long oldLen = NativeArray.validLength(oldLenDesc.getValue(), true);
+        // get old length and convert to long. Always a Long/Uint32 but we take the safe road.
+        final long oldLen = JSType.toUint32(oldLenDesc.getValue());
 
         // Step 3
         if ("length".equals(key)) {
@@ -471,7 +468,7 @@
     @Setter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
     public static void length(final Object self, final Object length) {
         if (isArray(self)) {
-            ((ScriptObject)self).setLength(validLength(length, true));
+            ((ScriptObject)self).setLength(validLength(length));
         }
     }
 
@@ -495,18 +492,13 @@
         length(self, length);  // Same as instance setter but we can't make nasgen use the same method for prototype
     }
 
-    static long validLength(final Object length, final boolean reject) {
+    static long validLength(final Object length) {
+        // ES5 15.4.5.1, steps 3.c and 3.d require two ToNumber conversions here
         final double doubleLength = JSType.toNumber(length);
-        if (!Double.isNaN(doubleLength) && JSType.isRepresentableAsLong(doubleLength)) {
-            final long len = (long) doubleLength;
-            if (len >= 0 && len <= JSType.MAX_UINT) {
-                return len;
-            }
-        }
-        if (reject) {
+        if (doubleLength != JSType.toUint32(length)) {
             throw rangeError("inappropriate.array.length", ScriptRuntime.safeToString(length));
         }
-        return -1;
+        return (long) doubleLength;
     }
 
     /**
@@ -1236,31 +1228,41 @@
         final List<Object> list = Arrays.asList(array);
         final Object cmpThis = cmp == null || cmp.isStrict() ? ScriptRuntime.UNDEFINED : Global.instance();
 
-        Collections.sort(list, new Comparator<Object>() {
-            private final MethodHandle call_cmp = getCALL_CMP();
-            @Override
-            public int compare(final Object x, final Object y) {
-                if (x == ScriptRuntime.UNDEFINED && y == ScriptRuntime.UNDEFINED) {
-                    return 0;
-                } else if (x == ScriptRuntime.UNDEFINED) {
-                    return 1;
-                } else if (y == ScriptRuntime.UNDEFINED) {
-                    return -1;
-                }
-
-                if (cmp != null) {
-                    try {
-                        return (int)Math.signum((double)call_cmp.invokeExact(cmp, cmpThis, x, y));
-                    } catch (final RuntimeException | Error e) {
-                        throw e;
-                    } catch (final Throwable t) {
-                        throw new RuntimeException(t);
+        try {
+            Collections.sort(list, new Comparator<Object>() {
+                private final MethodHandle call_cmp = getCALL_CMP();
+                @Override
+                public int compare(final Object x, final Object y) {
+                    if (x == ScriptRuntime.UNDEFINED && y == ScriptRuntime.UNDEFINED) {
+                        return 0;
+                    } else if (x == ScriptRuntime.UNDEFINED) {
+                        return 1;
+                    } else if (y == ScriptRuntime.UNDEFINED) {
+                        return -1;
                     }
-                }
 
-                return JSType.toString(x).compareTo(JSType.toString(y));
-            }
-        });
+                    if (cmp != null) {
+                        try {
+                            return (int)Math.signum((double)call_cmp.invokeExact(cmp, cmpThis, x, y));
+                        } catch (final RuntimeException | Error e) {
+                            throw e;
+                        } catch (final Throwable t) {
+                            throw new RuntimeException(t);
+                        }
+                    }
+
+                    return JSType.toString(x).compareTo(JSType.toString(y));
+                }
+            });
+        } catch (final IllegalArgumentException iae) {
+            // Collections.sort throws IllegalArgumentException when
+            // Comparison method violates its general contract
+
+            // See ECMA spec 15.4.4.11 Array.prototype.sort (comparefn).
+            // If "comparefn" is not undefined and is not a consistent
+            // comparison function for the elements of this array, the
+            // behaviour of sort is implementation-defined.
+        }
 
         return list.toArray(new Object[array.length]);
     }
diff --git a/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java b/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java
index e3c5c00..0d18edb 100644
--- a/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java
+++ b/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java
@@ -101,7 +101,7 @@
         }
 
         if (args.length == 0) {
-            throw new RuntimeException("missing length argument");
+            return new NativeArrayBuffer(0);
         }
 
         return new NativeArrayBuffer(JSType.toInt32(args[0]));
diff --git a/src/jdk/nashorn/internal/objects/NativeDataView.java b/src/jdk/nashorn/internal/objects/NativeDataView.java
index 14c11f6..44d0606 100644
--- a/src/jdk/nashorn/internal/objects/NativeDataView.java
+++ b/src/jdk/nashorn/internal/objects/NativeDataView.java
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package jdk.nashorn.internal.objects;
 
 import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
diff --git a/src/jdk/nashorn/internal/objects/NativeDate.java b/src/jdk/nashorn/internal/objects/NativeDate.java
index bb499c2..7462e4f 100644
--- a/src/jdk/nashorn/internal/objects/NativeDate.java
+++ b/src/jdk/nashorn/internal/objects/NativeDate.java
@@ -30,6 +30,7 @@
 import static java.lang.Double.isNaN;
 import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+
 import java.util.Locale;
 import java.util.TimeZone;
 import java.util.concurrent.Callable;
@@ -40,7 +41,6 @@
 import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
 import jdk.nashorn.internal.objects.annotations.Where;
 import jdk.nashorn.internal.parser.DateParser;
-import jdk.nashorn.internal.runtime.ConsString;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptEnvironment;
@@ -121,6 +121,10 @@
         this.timezone = env._timezone;
     }
 
+    NativeDate(final double time, final ScriptObject proto) {
+        this(time, proto, $nasgenmap$);
+    }
+
     NativeDate(final double time, final Global global) {
         this(time, global.getDatePrototype(), $nasgenmap$);
     }
@@ -183,7 +187,7 @@
         case 1:
             double num;
             final Object arg = JSType.toPrimitive(args[0]);
-            if (arg instanceof String || arg instanceof ConsString) {
+            if (JSType.isString(arg)) {
                 num = parseDateString(arg.toString());
             } else {
                 num = timeClip(JSType.toNumber(args[0]));
@@ -1276,7 +1280,7 @@
         if (self instanceof NativeDate) {
             return (NativeDate)self;
         } else if (self != null && self == Global.instance().getDatePrototype()) {
-            return Global.instance().DEFAULT_DATE;
+            return Global.instance().getDefaultDate();
         } else {
             throw typeError("not.a.date", ScriptRuntime.safeToString(self));
         }
diff --git a/src/jdk/nashorn/internal/objects/NativeDebug.java b/src/jdk/nashorn/internal/objects/NativeDebug.java
index c42e784..d517d39 100644
--- a/src/jdk/nashorn/internal/objects/NativeDebug.java
+++ b/src/jdk/nashorn/internal/objects/NativeDebug.java
@@ -26,6 +26,7 @@
 package jdk.nashorn.internal.objects;
 
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+
 import java.io.PrintWriter;
 import java.util.LinkedList;
 import java.util.Objects;
@@ -37,6 +38,7 @@
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.PropertyListeners;
 import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.Scope;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
@@ -245,7 +247,7 @@
         final PrintWriter out = Context.getCurrentErr();
 
         out.println("ScriptObject count " + ScriptObject.getCount());
-        out.println("Scope count " + ScriptObject.getScopeCount());
+        out.println("Scope count " + Scope.getScopeCount());
         out.println("ScriptObject listeners added " + PropertyListeners.getListenersAdded());
         out.println("ScriptObject listeners removed " + PropertyListeners.getListenersRemoved());
         out.println("ScriptFunction constructor calls " + ScriptFunction.getConstructorCount());
diff --git a/src/jdk/nashorn/internal/objects/NativeError.java b/src/jdk/nashorn/internal/objects/NativeError.java
index e1d95ce..036c8d8 100644
--- a/src/jdk/nashorn/internal/objects/NativeError.java
+++ b/src/jdk/nashorn/internal/objects/NativeError.java
@@ -150,8 +150,8 @@
         initException(sobj);
         sobj.delete(STACK, false);
         if (! sobj.has("stack")) {
-            final ScriptFunction getStack = ScriptFunctionImpl.makeFunction("getStack", GET_STACK);
-            final ScriptFunction setStack = ScriptFunctionImpl.makeFunction("setStack", SET_STACK);
+            final ScriptFunction getStack = ScriptFunction.createBuiltin("getStack", GET_STACK);
+            final ScriptFunction setStack = ScriptFunction.createBuiltin("setStack", SET_STACK);
             sobj.addOwnProperty("stack", Attribute.NOT_ENUMERABLE, getStack, setStack);
         }
         return UNDEFINED;
diff --git a/src/jdk/nashorn/internal/objects/NativeFloat32Array.java b/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
index ef7a1ff..b75d506 100644
--- a/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
@@ -114,12 +114,11 @@
 
         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();
+                if (index < nb.limit()) {
+                    nb.put(index, (float) elem);
                 }
+            } catch (final IndexOutOfBoundsException e) {
+                throw new ClassCastException();
             }
         }
 
diff --git a/src/jdk/nashorn/internal/objects/NativeFloat64Array.java b/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
index d0413d0..9a2e319 100644
--- a/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
@@ -114,12 +114,11 @@
 
         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();
+                if (index < nb.limit()) {
+                    nb.put(index, elem);
                 }
+            } catch (final IndexOutOfBoundsException e) {
+                throw new ClassCastException();
              }
         }
 
diff --git a/src/jdk/nashorn/internal/objects/NativeFunction.java b/src/jdk/nashorn/internal/objects/NativeFunction.java
index bd2f2dd..4b8029c 100644
--- a/src/jdk/nashorn/internal/objects/NativeFunction.java
+++ b/src/jdk/nashorn/internal/objects/NativeFunction.java
@@ -108,7 +108,7 @@
         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.
@@ -279,8 +279,8 @@
         sb.append("})");
 
         final Global global = Global.instance();
-
-        return (ScriptFunction)Global.directEval(global, sb.toString(), global, "<function>", global.isStrictContext());
+        final Context context = global.getContext();
+        return (ScriptFunction)context.eval(global, sb.toString(), global, "<function>");
     }
 
     private static void checkFunctionParameters(final String params) {
diff --git a/src/jdk/nashorn/internal/objects/NativeInt16Array.java b/src/jdk/nashorn/internal/objects/NativeInt16Array.java
index e4cdce5..c2eb555 100644
--- a/src/jdk/nashorn/internal/objects/NativeInt16Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeInt16Array.java
@@ -115,12 +115,11 @@
 
         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();
+                if (index < nb.limit()) {
+                    nb.put(index, (short) elem);
                 }
+            } catch (final IndexOutOfBoundsException e) {
+                throw new ClassCastException();
             }
         }
 
diff --git a/src/jdk/nashorn/internal/objects/NativeInt32Array.java b/src/jdk/nashorn/internal/objects/NativeInt32Array.java
index 9e664ed..a266fc5 100644
--- a/src/jdk/nashorn/internal/objects/NativeInt32Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeInt32Array.java
@@ -104,11 +104,11 @@
 
         private void setElem(final int index, final int elem) {
             try {
-                nb.put(index, elem);
-               } catch (final IndexOutOfBoundsException e) {
-                   if (index < 0) {
-                      throw new ClassCastException();
-                 }
+                if (index < nb.limit()) {
+                    nb.put(index, elem);
+                }
+            } catch (final IndexOutOfBoundsException e) {
+                throw new ClassCastException();
             }
         }
 
diff --git a/src/jdk/nashorn/internal/objects/NativeInt8Array.java b/src/jdk/nashorn/internal/objects/NativeInt8Array.java
index c336d27..be9bacf 100644
--- a/src/jdk/nashorn/internal/objects/NativeInt8Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeInt8Array.java
@@ -113,12 +113,11 @@
 
         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();
+                if (index < nb.limit()) {
+                    nb.put(index, (byte) elem);
                 }
+            } catch (final IndexOutOfBoundsException e) {
+                throw new ClassCastException();
             }
         }
 
diff --git a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java
index c5ca910..32e41da 100644
--- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java
+++ b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java
@@ -160,7 +160,7 @@
     }
 
     private static ScriptObject wrapAdaptee(final ScriptObject adaptee) {
-        return new JO(adaptee, JO.getInitialMap());
+        return new JO(adaptee);
     }
 
     @Override
@@ -621,13 +621,13 @@
             if (find != null) {
                 final Object value = find.getObjectValue();
                 if (value instanceof ScriptFunction) {
-                    final ScriptFunctionImpl func = (ScriptFunctionImpl)value;
+                    final ScriptFunction func = (ScriptFunction)value;
                     // TODO: It's a shame we need to produce a function bound to this and name, when we'd only need it bound
                     // 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),
+                            func.createBound(this, new Object[] { name })), 0, Object.class),
                             testJSAdaptor(adaptee, null, null, null),
-                            adaptee.getProtoSwitchPoint(__call__, find.getOwner()));
+                            adaptee.getProtoSwitchPoints(__call__, find.getOwner()), null);
                 }
             }
             throw typeError("no.such.function", desc.getNameToken(2), ScriptRuntime.safeToString(this));
@@ -698,7 +698,7 @@
                     return new GuardedInvocation(
                             methodHandle,
                             testJSAdaptor(adaptee, findData.getGetter(Object.class, INVALID_PROGRAM_POINT, null), findData.getOwner(), func),
-                            adaptee.getProtoSwitchPoint(hook, findData.getOwner()));
+                            adaptee.getProtoSwitchPoints(hook, findData.getOwner()), null);
                 }
              }
         }
@@ -710,7 +710,7 @@
             final MethodHandle methodHandle = hook.equals(__put__) ?
             MH.asType(Lookup.EMPTY_SETTER, type) :
             Lookup.emptyGetter(type.returnType());
-            return new GuardedInvocation(methodHandle, testJSAdaptor(adaptee, null, null, null), adaptee.getProtoSwitchPoint(hook, null));
+            return new GuardedInvocation(methodHandle, testJSAdaptor(adaptee, null, null, null), adaptee.getProtoSwitchPoints(hook, null), null);
         }
     }
 
diff --git a/src/jdk/nashorn/internal/objects/NativeJSON.java b/src/jdk/nashorn/internal/objects/NativeJSON.java
index 7bd8a4a..877de50 100644
--- a/src/jdk/nashorn/internal/objects/NativeJSON.java
+++ b/src/jdk/nashorn/internal/objects/NativeJSON.java
@@ -181,7 +181,7 @@
                 }
                 gap = sb.toString();
             }
-        } else if (modSpace instanceof String || modSpace instanceof ConsString) {
+        } else if (JSType.isString(modSpace)) {
             final String str = modSpace.toString();
             gap = str.substring(0, Math.min(10, str.length()));
         } else {
diff --git a/src/jdk/nashorn/internal/objects/NativeJava.java b/src/jdk/nashorn/internal/objects/NativeJava.java
index 7c6e60a..79a190f 100644
--- a/src/jdk/nashorn/internal/objects/NativeJava.java
+++ b/src/jdk/nashorn/internal/objects/NativeJava.java
@@ -33,10 +33,12 @@
 import java.util.Collection;
 import java.util.Deque;
 import java.util.List;
+import java.util.Map;
+import java.util.Queue;
 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.api.scripting.ScriptObjectMirror;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Function;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
@@ -91,7 +93,7 @@
     @Function(name="synchronized", attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
     public static Object synchronizedFunc(final Object self, final Object func, final Object obj) {
         if (func instanceof ScriptFunction) {
-            return ((ScriptFunction)func).makeSynchronizedFunction(obj);
+            return ((ScriptFunction)func).createSynchronized(obj);
         }
 
         throw typeError("not.a.function", ScriptRuntime.safeToString(func));
@@ -339,7 +341,9 @@
 
     /**
      * Given a script object and a Java type, converts the script object into the desired Java type. Currently it
-     * performs shallow creation of Java arrays, as well as wrapping of objects in Lists and Dequeues. Example:
+     * performs shallow creation of Java arrays, as well as wrapping of objects in Lists, Dequeues, Queues,
+     * and Collections. If conversion is not possible or fails for some reason, TypeError is thrown.
+     * Example:
      * <pre>
      * var anArray = [1, "13", false]
      * var javaIntArray = Java.to(anArray, "int[]")
@@ -353,9 +357,10 @@
      * object to create. Can not be null. If undefined, a "default" conversion is presumed (allowing the argument to be
      * omitted).
      * @return a Java object whose value corresponds to the original script object's value. Specifically, for array
-     * target types, returns a Java array of the same type with contents converted to the array's component type. Does
-     * not recursively convert for multidimensional arrays. For {@link List} or {@link Deque}, returns a live wrapper
-     * around the object, see {@link ListAdapter} for details. Returns null if obj is null.
+     * target types, returns a Java array of the same type with contents converted to the array's component type.
+     * Converts recursively when the target type is multidimensional array. For {@link List}, {@link Deque},
+     * {@link Queue}, or {@link Collection}, returns a live wrapper around the object, see {@link ListAdapter} for
+     * details. Returns null if obj is null.
      * @throws ClassNotFoundException if the class described by objType is not found
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
@@ -382,10 +387,14 @@
         }
 
         if(targetClass.isArray()) {
-            return JSType.toJavaArray(obj, targetClass.getComponentType());
+            try {
+                return JSType.toJavaArray(obj, targetClass.getComponentType());
+            } catch (final Exception exp) {
+                throw typeError(exp, "java.array.conversion.failed", targetClass.getName());
+            }
         }
 
-        if(targetClass == List.class || targetClass == Deque.class) {
+        if (targetClass == List.class || targetClass == Deque.class || targetClass == Queue.class || targetClass == Collection.class) {
             return ListAdapter.create(obj);
         }
 
@@ -654,4 +663,20 @@
     public static Object _super(final Object self, final Object adapter) {
         return Bootstrap.createSuperAdapter(adapter);
     }
+
+    /**
+     * Returns an object that is compatible with Java JSON libraries expectations; namely, that if it itself, or any
+     * object transitively reachable through it is a JavaScript array, then such objects will be exposed as
+     * {@link JSObject} that also implements the {@link List} interface for exposing the array elements. An explicit
+     * API is required as otherwise Nashorn exposes all objects externally as {@link JSObject}s that also implement the
+     * {@link Map} interface instead. By using this method, arrays will be exposed as {@link List}s and all other
+     * objects as {@link Map}s.
+     * @param self not used
+     * @param obj the object to be exposed in a Java JSON library compatible manner.
+     * @return a wrapper around the object that will enforce Java JSON library compatible exposure.
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static Object asJSONCompatible(final Object self, final Object obj) {
+        return ScriptObjectMirror.wrapAsJSONCompatible(obj, Context.getGlobal());
+    }
 }
diff --git a/src/jdk/nashorn/internal/objects/NativeJavaImporter.java b/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
index 498c263..67494b2 100644
--- a/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
+++ b/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
@@ -134,7 +134,7 @@
     }
 
     @Override
-    protected Object invokeNoSuchProperty(final String name, final int programPoint) {
+    protected Object invokeNoSuchProperty(final String name, final boolean isScope, final int programPoint) {
         final Object retval = createProperty(name);
         if (isValid(programPoint)) {
             throw new UnwarrantedOptimismException(retval, programPoint);
diff --git a/src/jdk/nashorn/internal/objects/NativeNumber.java b/src/jdk/nashorn/internal/objects/NativeNumber.java
index 7ea2783..3cbe5eb 100644
--- a/src/jdk/nashorn/internal/objects/NativeNumber.java
+++ b/src/jdk/nashorn/internal/objects/NativeNumber.java
@@ -33,6 +33,7 @@
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
+import java.math.RoundingMode;
 import java.text.NumberFormat;
 import java.util.Locale;
 import jdk.internal.dynalink.linker.GuardedInvocation;
@@ -187,6 +188,7 @@
         format.setMinimumFractionDigits(fractionDigits);
         format.setMaximumFractionDigits(fractionDigits);
         format.setGroupingUsed(false);
+        format.setRoundingMode(RoundingMode.HALF_UP);
 
         return format.format(x);
     }
diff --git a/src/jdk/nashorn/internal/objects/NativeObject.java b/src/jdk/nashorn/internal/objects/NativeObject.java
index c086442..7dc154e 100644
--- a/src/jdk/nashorn/internal/objects/NativeObject.java
+++ b/src/jdk/nashorn/internal/objects/NativeObject.java
@@ -499,7 +499,7 @@
         final Object obj = JSType.toScriptObject(self);
         if (obj instanceof ScriptObject) {
             final InvokeByName toStringInvoker = getTO_STRING();
-            final ScriptObject sobj = (ScriptObject)self;
+            final ScriptObject sobj = (ScriptObject)obj;
             try {
                 final Object toString = toStringInvoker.getGetter().invokeExact(sobj);
 
@@ -765,7 +765,7 @@
                 continue;
             }
             properties.add(AccessorProperty.create(methodName, Property.NOT_WRITABLE, getBoundBeanMethodGetter(source,
-                    method), null));
+                    method), Lookup.EMPTY_SETTER));
         }
         for(final String propertyName: propertyNames) {
             MethodHandle getter;
diff --git a/src/jdk/nashorn/internal/objects/NativeRegExp.java b/src/jdk/nashorn/internal/objects/NativeRegExp.java
index 33ef284..da64372 100644
--- a/src/jdk/nashorn/internal/objects/NativeRegExp.java
+++ b/src/jdk/nashorn/internal/objects/NativeRegExp.java
@@ -78,8 +78,8 @@
         this.globalObject = global;
     }
 
-    NativeRegExp(final String input, final String flagString, final Global global) {
-        this(global);
+    NativeRegExp(final String input, final String flagString, final Global global, final ScriptObject proto) {
+        super(proto, $nasgenmap$);
         try {
             this.regexp = RegExpFactory.create(input, flagString);
         } catch (final ParserException e) {
@@ -87,10 +87,14 @@
             e.throwAsEcmaException();
             throw new AssertionError(); //guard against null warnings below
         }
-
+        this.globalObject = global;
         this.setLastIndex(0);
     }
 
+    NativeRegExp(final String input, final String flagString, final Global global) {
+        this(input, flagString, global, global.getRegExpPrototype());
+    }
+
     NativeRegExp(final String input, final String flagString) {
         this(input, flagString, Global.instance());
     }
@@ -724,7 +728,7 @@
          *
          * $$ -> $
          * $& -> the matched substring
-         * $` -> the portion of string that preceeds matched substring
+         * $` -> the portion of string that precedes matched substring
          * $' -> the portion of string that follows the matched substring
          * $n -> the nth capture, where n is [1-9] and $n is NOT followed by a decimal digit
          * $nn -> the nnth capture, where nn is a two digit decimal number [01-99].
@@ -928,7 +932,7 @@
         if (self instanceof NativeRegExp) {
             return (NativeRegExp)self;
         } else if (self != null && self == Global.instance().getRegExpPrototype()) {
-            return Global.instance().DEFAULT_REGEXP;
+            return Global.instance().getDefaultRegExp();
         } else {
             throw typeError("not.a.regexp", ScriptRuntime.safeToString(self));
         }
diff --git a/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java b/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java
index 467399a..0df0eca 100644
--- a/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java
+++ b/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java
@@ -88,7 +88,7 @@
     @Setter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
     public static void length(final Object self, final Object length) {
         if (self instanceof ScriptObject) {
-            ((ScriptObject)self).setLength(NativeArray.validLength(length, true));
+            ((ScriptObject)self).setLength(NativeArray.validLength(length));
         }
     }
 }
diff --git a/src/jdk/nashorn/internal/objects/NativeString.java b/src/jdk/nashorn/internal/objects/NativeString.java
index 7fb86a4..8585657 100644
--- a/src/jdk/nashorn/internal/objects/NativeString.java
+++ b/src/jdk/nashorn/internal/objects/NativeString.java
@@ -90,7 +90,7 @@
 
     private NativeString(final CharSequence value, final ScriptObject proto, final PropertyMap map) {
         super(proto, map);
-        assert value instanceof String || value instanceof ConsString;
+        assert JSType.isString(value);
         this.value = value;
     }
 
@@ -155,7 +155,7 @@
         final Object self = request.getReceiver();
         final Class<?> returnType = desc.getMethodType().returnType();
 
-        if (returnType == Object.class && (self instanceof String || self instanceof ConsString)) {
+        if (returnType == Object.class && JSType.isString(self)) {
             try {
                 return new GuardedInvocation(MH.findStatic(MethodHandles.lookup(), NativeString.class, "get", desc.getMethodType()), NashornGuards.getInstanceOf2Guard(String.class, ConsString.class));
             } catch (final LookupException e) {
@@ -1312,7 +1312,7 @@
     }
 
     private static CharSequence getCharSequence(final Object self) {
-        if (self instanceof String || self instanceof ConsString) {
+        if (JSType.isString(self)) {
             return (CharSequence)self;
         } else if (self instanceof NativeString) {
             return ((NativeString)self).getValue();
diff --git a/src/jdk/nashorn/internal/objects/NativeUint16Array.java b/src/jdk/nashorn/internal/objects/NativeUint16Array.java
index 2fc2c51..30dc681 100644
--- a/src/jdk/nashorn/internal/objects/NativeUint16Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeUint16Array.java
@@ -104,12 +104,11 @@
 
         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();
+                if (index < nb.limit()) {
+                    nb.put(index, (char) elem);
                 }
+            } catch (final IndexOutOfBoundsException e) {
+                throw new ClassCastException();
             }
         }
 
diff --git a/src/jdk/nashorn/internal/objects/NativeUint32Array.java b/src/jdk/nashorn/internal/objects/NativeUint32Array.java
index 4c83cc0..8503517 100644
--- a/src/jdk/nashorn/internal/objects/NativeUint32Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeUint32Array.java
@@ -113,12 +113,11 @@
 
         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();
+                if (index < nb.limit()) {
+                    nb.put(index, elem);
                 }
+            } catch (final IndexOutOfBoundsException e) {
+                throw new ClassCastException();
             }
         }
 
diff --git a/src/jdk/nashorn/internal/objects/NativeUint8Array.java b/src/jdk/nashorn/internal/objects/NativeUint8Array.java
index 6e69eba..f5ccce6 100644
--- a/src/jdk/nashorn/internal/objects/NativeUint8Array.java
+++ b/src/jdk/nashorn/internal/objects/NativeUint8Array.java
@@ -104,12 +104,11 @@
 
         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();
+                if (index < nb.limit()) {
+                    nb.put(index, (byte) elem);
                 }
+            } catch (final IndexOutOfBoundsException e) {
+                throw new ClassCastException();
             }
         }
 
diff --git a/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java b/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
index 2dff261..28d72d1 100644
--- a/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
+++ b/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
@@ -133,18 +133,17 @@
 
         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;
+                if (index < nb.limit()) {
+                    final byte clamped;
+                    if ((elem & 0xffff_ff00) == 0) {
+                        clamped = (byte) elem;
+                    } else {
+                        clamped = elem < 0 ? 0 : (byte) 0xff;
+                    }
+                    nb.put(index, clamped);
                 }
-                nb.put(index, clamped);
             } catch (final IndexOutOfBoundsException e) {
-                //swallow valid array indexes. it's ok.
-                if (index < 0) {
-                    throw new ClassCastException();
-                }
+                throw new ClassCastException();
             }
         }
 
diff --git a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
deleted file mode 100644
index f147234..0000000
--- a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
+++ /dev/null
@@ -1,300 +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.objects;
-
-import static jdk.nashorn.internal.lookup.Lookup.MH;
-import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-
-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;
-import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
-import jdk.nashorn.internal.runtime.ScriptFunction;
-import jdk.nashorn.internal.runtime.ScriptFunctionData;
-import jdk.nashorn.internal.runtime.ScriptObject;
-import jdk.nashorn.internal.runtime.Specialization;
-
-/**
- * Concrete implementation of ScriptFunction. This sets correct map for the
- * function objects -- to expose properties like "prototype", "length" etc.
- */
-public class ScriptFunctionImpl extends ScriptFunction {
-
-    /** Reference to constructor prototype. */
-    private Object prototype;
-
-    // property map for strict mode functions
-    private static final PropertyMap strictmodemap$;
-    // property map for bound functions
-    private static final PropertyMap boundfunctionmap$;
-    // property map for non-strict, non-bound functions.
-    private static final PropertyMap map$;
-
-    // Marker object for lazily initialized prototype object
-    private static final Object LAZY_PROTOTYPE = new Object();
-
-    private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final Specialization[] specs, final Global global) {
-        super(name, invokeHandle, map$, null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR);
-        init(global);
-    }
-
-    /**
-     * Constructor called by Nasgen generated code, no membercount, use the default map.
-     * Creates builtin functions only.
-     *
-     * @param name name of function
-     * @param invokeHandle handle for invocation
-     * @param specs specialized versions of this method, if available, null otherwise
-     */
-    ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final Specialization[] specs) {
-        this(name, invokeHandle, specs, Global.instance());
-    }
-
-    private ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final Specialization[] specs, final Global global) {
-        super(name, invokeHandle, map.addAll(map$), null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR);
-        init(global);
-    }
-
-    /**
-     * Constructor called by Nasgen generated code, no membercount, use the map passed as argument.
-     * Creates builtin functions only.
-     *
-     * @param name name of function
-     * @param invokeHandle handle for invocation
-     * @param map initial property map
-     * @param specs specialized versions of this method, if available, null otherwise
-     */
-    ScriptFunctionImpl(final String name, final MethodHandle invokeHandle, final PropertyMap map, final Specialization[] specs) {
-        this(name, invokeHandle, map, specs, Global.instance());
-    }
-
-    private ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final Specialization[] specs, final int flags, final Global global) {
-        super(name, methodHandle, getMap(isStrict(flags)), scope, specs, flags);
-        init(global);
-    }
-
-    /**
-     * Constructor called by Global.newScriptFunction (runtime).
-     *
-     * @param name name of function
-     * @param methodHandle handle for invocation
-     * @param scope scope object
-     * @param specs specialized versions of this method, if available, null otherwise
-     * @param flags {@link ScriptFunctionData} flags
-     */
-    ScriptFunctionImpl(final String name, final MethodHandle methodHandle, final ScriptObject scope, final Specialization[] specs, final int flags) {
-        this(name, methodHandle, scope, specs, flags, Global.instance());
-    }
-
-    private ScriptFunctionImpl(final RecompilableScriptFunctionData data, final ScriptObject scope, final Global global) {
-        super(data, getMap(data.isStrict()), scope);
-        init(global);
-    }
-
-    /**
-     * Constructor called by (compiler) generated code for {@link ScriptObject}s.
-     *
-     * @param data static function data
-     * @param scope scope object
-     */
-    public ScriptFunctionImpl(final RecompilableScriptFunctionData data, final ScriptObject scope) {
-        this(data, scope, Global.instance());
-    }
-
-    /**
-     * Only invoked internally from {@link BoundScriptFunctionImpl} constructor.
-     * @param data the script function data for the bound function.
-     * @param global the global object
-     */
-    ScriptFunctionImpl(final ScriptFunctionData data, final Global global) {
-        super(data, boundfunctionmap$, null);
-        init(global);
-    }
-
-    static {
-        final ArrayList<Property> properties = new ArrayList<>(3);
-        properties.add(AccessorProperty.create("prototype", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE, G$PROTOTYPE, S$PROTOTYPE));
-        properties.add(AccessorProperty.create("length",  Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$LENGTH, null));
-        properties.add(AccessorProperty.create("name", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$NAME, null));
-        map$ = PropertyMap.newMap(properties);
-        strictmodemap$ = createStrictModeMap(map$);
-        boundfunctionmap$ = createBoundFunctionMap(strictmodemap$);
-    }
-
-    private static PropertyMap createStrictModeMap(final PropertyMap map) {
-        final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
-        PropertyMap newMap = map;
-        // Need to add properties directly to map since slots are assigned speculatively by newUserAccessors.
-        newMap = newMap.addPropertyNoHistory(map.newUserAccessors("arguments", flags));
-        newMap = newMap.addPropertyNoHistory(map.newUserAccessors("caller", flags));
-        return newMap;
-    }
-
-    private static boolean isStrict(final int flags) {
-        return (flags & ScriptFunctionData.IS_STRICT) != 0;
-    }
-
-    // Choose the map based on strict mode!
-    private static PropertyMap getMap(final boolean strict) {
-        return strict ? strictmodemap$ : map$;
-    }
-
-    private static PropertyMap createBoundFunctionMap(final PropertyMap strictModeMap) {
-        // Bound function map is same as strict function map, but additionally lacks the "prototype" property, see
-        // ECMAScript 5.1 section 15.3.4.5
-        return strictModeMap.deleteProperty(strictModeMap.findProperty("prototype"));
-    }
-
-    // Instance of this class is used as global anonymous function which
-    // serves as Function.prototype object.
-    private static class AnonymousFunction extends ScriptFunctionImpl {
-        private static final PropertyMap anonmap$ = PropertyMap.newMap();
-
-        AnonymousFunction() {
-            super("", GlobalFunctions.ANONYMOUS, anonmap$, null);
-        }
-    }
-
-    static ScriptFunctionImpl newAnonymousFunction() {
-        return new AnonymousFunction();
-    }
-
-    private static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final Specialization[] 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;
-    }
-
-    /**
-     * Factory method for non-constructor built-in functions
-     *
-     * @param name   function name
-     * @param methodHandle handle for invocation
-     * @param specs  specialized versions of function if available, null otherwise
-     * @return new ScriptFunction
-     */
-    static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final Specialization[] specs) {
-        return makeFunction(name, methodHandle, specs, ScriptFunctionData.IS_BUILTIN);
-    }
-
-    /**
-     * 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 );
-    }
-
-    /**
-     * Factory method for non-constructor built-in functions
-     *
-     * @param name   function name
-     * @param methodHandle handle for invocation
-     * @return new ScriptFunction
-     */
-    static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle) {
-        return makeFunction(name, methodHandle, null);
-    }
-
-    @Override
-    public ScriptFunction makeSynchronizedFunction(final Object sync) {
-        final MethodHandle mh = MH.insertArguments(ScriptFunction.INVOKE_SYNC, 0, this, sync);
-        return makeFunction(getName(), mh);
-    }
-
-    /**
-     * Same as {@link ScriptFunction#makeBoundFunction(Object, Object[])}. The only reason we override it is so that we
-     * can expose it.
-     * @param self the self to bind to this function. Can be null (in which case, null is bound as this).
-     * @param args additional arguments to bind to this function. Can be null or empty to not bind additional arguments.
-     * @return a function with the specified self and parameters bound.
-     */
-    @Override
-    public ScriptFunction makeBoundFunction(final Object self, final Object[] args) {
-        return super.makeBoundFunction(self, args);
-    }
-
-    /**
-     * This method is used to create a bound function based on this function.
-     *
-     * @param data the {@code ScriptFunctionData} specifying the functions immutable portion.
-     * @return a function initialized from the specified data. Its parent scope will be set to null, therefore the
-     * passed in data should not expect a callee.
-     */
-    @Override
-    protected ScriptFunction makeBoundFunction(final ScriptFunctionData data) {
-        return new BoundScriptFunctionImpl(data, getTargetFunction());
-    }
-
-    // return Object.prototype - used by "allocate"
-    @Override
-    protected final ScriptObject getObjectPrototype() {
-        return Global.objectPrototype();
-    }
-
-    @Override
-    public final Object getPrototype() {
-        if (prototype == LAZY_PROTOTYPE) {
-            prototype = new PrototypeObject(this);
-        }
-        return prototype;
-    }
-
-    @Override
-    public final void setPrototype(final Object newProto) {
-        if (newProto instanceof ScriptObject && newProto != this.prototype && allocatorMap != null) {
-            // Replace our current allocator map with one that is associated with the new prototype.
-            allocatorMap = allocatorMap.changeProto((ScriptObject)newProto);
-        }
-        this.prototype = newProto;
-    }
-
-    // Internals below..
-    private void init(final Global global) {
-        this.setInitialProto(global.getFunctionPrototype());
-        this.prototype = LAZY_PROTOTYPE;
-
-        // We have to fill user accessor functions late as these are stored
-        // in this object rather than in the PropertyMap of this object.
-        assert objectSpill == null;
-        final ScriptFunction typeErrorThrower = global.getTypeErrorThrower();
-        if (findProperty("arguments", true) != null) {
-            initUserAccessors("arguments", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower);
-       }
-        if (findProperty("caller", true) != null) {
-            initUserAccessors("caller", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower);
-       }
-    }
-}
diff --git a/src/jdk/nashorn/internal/objects/annotations/Constructor.java b/src/jdk/nashorn/internal/objects/annotations/Constructor.java
index 297bb1e..a04a2ba 100644
--- a/src/jdk/nashorn/internal/objects/annotations/Constructor.java
+++ b/src/jdk/nashorn/internal/objects/annotations/Constructor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,13 +37,15 @@
 @Target(ElementType.METHOD)
 public @interface Constructor {
     /**
-     * Name of the constructor function. If empty, the name is inferred.
+     * @return the name of the constructor function. If empty, the name is
+     *         inferred.
      */
     public String name() default "";
 
     /**
-     * The arity of the function. By default computed from the method signature.
-     * Note that -1 means varargs. So, -2 is used as invalid arity.
+     * @return the arity of the function. By default computed from the method
+     *         signature. Note that -1 means varargs. So, -2 is used as invalid
+     *         arity.
      */
     public int arity() default -2;
 }
diff --git a/src/jdk/nashorn/internal/objects/annotations/Function.java b/src/jdk/nashorn/internal/objects/annotations/Function.java
index 04c5393..b405f3c 100644
--- a/src/jdk/nashorn/internal/objects/annotations/Function.java
+++ b/src/jdk/nashorn/internal/objects/annotations/Function.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,22 +41,23 @@
 @Target(ElementType.METHOD)
 public @interface Function {
     /**
-     * Name of the property. If empty, the name is inferred.
+     * @return the name of the property. If empty, the name is inferred.
      */
     public String name() default "";
 
     /**
-     * Attribute flags for this function.
+     * @return the attribute flags for this function.
      */
     public int attributes() default DEFAULT_ATTRIBUTES;
 
     /**
-     * The arity of the function. By default computed from the method signature
+     * @return the arity of the function. By default computed from the method
+     *         signature.
      */
     public int arity() default -2;
 
     /**
-     * where this function lives
+     * @return where this function lives.
      */
     public Where where() default Where.PROTOTYPE;
 }
diff --git a/src/jdk/nashorn/internal/objects/annotations/Getter.java b/src/jdk/nashorn/internal/objects/annotations/Getter.java
index d10bbf6..f20b7e8 100644
--- a/src/jdk/nashorn/internal/objects/annotations/Getter.java
+++ b/src/jdk/nashorn/internal/objects/annotations/Getter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,17 +39,17 @@
 @Target(ElementType.METHOD)
 public @interface Getter {
     /**
-     * Name of the property. If empty, the name is inferred.
+     * @return the name of the property. If empty, the name is inferred.
      */
     public String name() default "";
 
     /**
-     * Attribute flags for this setter.
+     * @return the attribute flags for this setter.
      */
     public int attributes() default DEFAULT_ATTRIBUTES;
 
     /**
-     * Where this getter lives?
+     * @return where this getter lives.
      */
     public Where where() default Where.INSTANCE;
 }
diff --git a/src/jdk/nashorn/internal/objects/annotations/ScriptClass.java b/src/jdk/nashorn/internal/objects/annotations/ScriptClass.java
index 23d910c..4c0e0b2 100644
--- a/src/jdk/nashorn/internal/objects/annotations/ScriptClass.java
+++ b/src/jdk/nashorn/internal/objects/annotations/ScriptClass.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,8 +37,8 @@
 @Target(ElementType.TYPE)
 public @interface ScriptClass {
     /**
-     * Name of the script class. By default, the name is derived from
-     * the Java class name.
+     * @return the name of the script class. By default, the name is derived
+     *         from the Java class name.
      */
     public String value() default "";
 }
diff --git a/src/jdk/nashorn/internal/objects/annotations/Setter.java b/src/jdk/nashorn/internal/objects/annotations/Setter.java
index bad6f2a..beeca98 100644
--- a/src/jdk/nashorn/internal/objects/annotations/Setter.java
+++ b/src/jdk/nashorn/internal/objects/annotations/Setter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,17 +39,17 @@
 @Target(ElementType.METHOD)
 public @interface Setter {
     /**
-     * Name of the script property. If empty, the name is inferred.
+     * @return the name of the script property. If empty, the name is inferred.
      */
     public String name() default "";
 
     /**
-     * Attribute flags for this setter.
+     * @return the attribute flags for this setter.
      */
     public int attributes() default DEFAULT_ATTRIBUTES;
 
     /**
-     * Where this setter lives?
+     * @return where this setter lives.
      */
     public Where where() default Where.INSTANCE;
 }
diff --git a/src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java b/src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java
index 62e6e99..0544c0f 100644
--- a/src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java
+++ b/src/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,10 +33,11 @@
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.nashorn.internal.runtime.ScriptFunction;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
 
 /**
  * The SpecializedFunction annotation is used to flag more type specific
- * functions than the standard one in the native objects
+ * functions than the standard one in the native objects.
  */
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.METHOD)
@@ -45,23 +46,23 @@
     /**
      * Functionality for testing if we are allowed to link a specialized
      * function the first time we encounter it. Then the guard will handle the
-     * rest of the invocations
+     * rest of the invocations.
      *
-     * This is the same for all callsites in Nashorn, the first time callsite is
+     * This is the same for all callsites in Nashorn; the first time a callsite is
      * linked, we have to manually check that the linkage is OK. Even if we add
      * a guard and it fails upon the first try, this is not good enough.
-     * (Symmetrical to how it works everywhere else in the Nashorn runtime).
+     * (Symmetrical to how it works everywhere else in the Nashorn runtime.)
      *
      * Here we abstract out a few of the most common link guard checks.
      */
     public static abstract class LinkLogic {
         /**
-         * Empty link logic instance - this is the default
+         * Empty link logic instance - this is the default.
          * "no special linking or runtime guard behavior"
          */
         public static final LinkLogic EMPTY_INSTANCE = new Empty();
 
-        /** Empty link logic class - allow all linking, no guards */
+        /** Empty link logic class - allow all linking, no guards. */
         private static final class Empty extends LinkLogic {
             @Override
             public boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request) {
@@ -75,7 +76,8 @@
         }
 
         /**
-         * Get the class representing the empty link logic
+         * Get the class representing the empty link logic.
+         *
          * @return class representing empty link logic
          */
         public static Class<? extends LinkLogic> getEmptyLinkLogicClass() {
@@ -83,31 +85,31 @@
         }
 
         /**
-         * Should this callsite relink when an exception is thrown
+         * Should this callsite relink when an exception is thrown?
          *
-         * @return the relink exception, or null if none
+         * @return the relink exception, or {@code null} if none
          */
         public Class<? extends Throwable> getRelinkException() {
             return null;
         }
 
         /**
-         * Is this link logic class empty - i.e. no special linking logic
-         * supplied
+         * Is this link logic class empty - i.e., no special linking logic
+         * supplied?
          *
          * @param clazz class to check
          *
-         * @return true if this link logic is empty
+         * @return {@code true} if this link logic is empty
          */
         public static boolean isEmpty(final Class<? extends LinkLogic> clazz) {
             return clazz == Empty.class;
         }
 
         /**
-         * Is this link logic instance empty - i.e. no special linking logic
-         * supplied
+         * Is this link logic instance empty - i.e., no special linking logic
+         * supplied?
          *
-         * @return true if this link logic instance is empty
+         * @return {@code true} if this link logic instance is empty
          */
         public boolean isEmpty() {
             return false;
@@ -121,7 +123,7 @@
          * @param desc    callsite descriptor
          * @param request link request
          *
-         * @return true if we can link this callsite at this time
+         * @return {@code true} if we can link this callsite at this time
          */
         public abstract boolean canLink(final Object self, final CallSiteDescriptor desc, final LinkRequest request);
 
@@ -131,7 +133,7 @@
          *
          * @param self receiver
          *
-         * @return true if a guard is to be woven into the callsite
+         * @return {@code true} if a guard is to be woven into the callsite
          */
         public boolean needsGuard(final Object self) {
             return true;
@@ -139,13 +141,13 @@
 
         /**
          * Given a callsite, and optional arguments, do we need an extra guard
-         * for specialization to go through - this guard can be a function of
-         * the arguments too
+         * for specialization to go through? This guard can be a function of
+         * the arguments too.
          *
          * @param self receiver
          * @param args arguments
          *
-         * @return true if a guard is to be woven into the callsite
+         * @return {@code true} if a guard is to be woven into the callsite
          */
         public boolean needsGuard(final Object self, final Object... args) {
             return true;
@@ -169,9 +171,9 @@
          * @param self receiver
          * @param desc callsite descriptor
          * @param request link request
-
-         * @return true if we can link, false otherwise - that means we have to
-         *         pick a non specialized target
+         *
+         * @return {@code true} if we can link, {@code false} otherwise - that
+         *         means we have to pick a non specialized target
          */
         public boolean checkLinkable(final Object self, final CallSiteDescriptor desc, final LinkRequest request) {
             // check the link guard, if it says we can link, go ahead
@@ -180,11 +182,11 @@
     }
 
     /**
-     * name override for return value polymorphism, for example we can't have
+     * Name override for return value polymorphism, for example we can't have
      * pop(V)I and pop(V)D in the same Java class, so they need to be named,
-     * e.g. popInt(V)I and popDouble(V)D for disambiguation, however, their
+     * e.g., popInt(V)I and popDouble(V)D for disambiguation, however, their
      * names still need to resolve to "pop" to JavaScript so we can still
-     * specialize on return values and so that the linker can find them
+     * specialize on return values and so that the linker can find them.
      *
      * @return name, "" means no override, use the Java function name, e.g.
      *         "push"
@@ -199,16 +201,18 @@
     Class<?> linkLogic() default LinkLogic.Empty.class;
 
     /**
-     * Is this a specialized constructor?
+     * @return whether this is a specialized constructor.
      */
     boolean isConstructor() default false;
 
     /**
-     * Can this function throw UnwarrantedOptimismExceptions? This works just
-     * like the normal functions, but we need the function to be
+     * Can this function throw {@link UnwarrantedOptimismException}s? This works
+     * just like the normal functions, but we need the function to be
      * immutable/non-state modifying, as we can't generate continuations for
      * native code. Luckily a lot of the methods we want to specialize have this
-     * property
+     * property.
+     *
+     * @return whether this function can throw {@link UnwarrantedOptimismException}.
      */
     boolean isOptimistic() default false;
 }
diff --git a/src/jdk/nashorn/internal/parser/AbstractParser.java b/src/jdk/nashorn/internal/parser/AbstractParser.java
index 3eb45cf..a7c7fb9 100644
--- a/src/jdk/nashorn/internal/parser/AbstractParser.java
+++ b/src/jdk/nashorn/internal/parser/AbstractParser.java
@@ -459,6 +459,19 @@
         if (kind == TokenKind.KEYWORD || kind == TokenKind.FUTURE || kind == TokenKind.FUTURESTRICT) {
             return true;
         }
+
+        // only literals allowed are null, false and true
+        if (kind == TokenKind.LITERAL) {
+            switch (type) {
+                case FALSE:
+                case NULL:
+                case TRUE:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
         // Fake out identifier.
         final long identToken = Token.recast(token, IDENT);
         // Get IDENT.
diff --git a/src/jdk/nashorn/internal/parser/JSONParser.java b/src/jdk/nashorn/internal/parser/JSONParser.java
index 7faf89a..ac40213 100644
--- a/src/jdk/nashorn/internal/parser/JSONParser.java
+++ b/src/jdk/nashorn/internal/parser/JSONParser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,43 +25,69 @@
 
 package jdk.nashorn.internal.parser;
 
-import static jdk.nashorn.internal.parser.TokenType.COLON;
-import static jdk.nashorn.internal.parser.TokenType.COMMARIGHT;
-import static jdk.nashorn.internal.parser.TokenType.EOF;
-import static jdk.nashorn.internal.parser.TokenType.ESCSTRING;
-import static jdk.nashorn.internal.parser.TokenType.RBRACE;
-import static jdk.nashorn.internal.parser.TokenType.RBRACKET;
-import static jdk.nashorn.internal.parser.TokenType.STRING;
 import java.util.ArrayList;
 import java.util.List;
-import jdk.nashorn.internal.ir.Expression;
-import jdk.nashorn.internal.ir.LiteralNode;
-import jdk.nashorn.internal.ir.Node;
-import jdk.nashorn.internal.ir.ObjectNode;
-import jdk.nashorn.internal.ir.PropertyNode;
-import jdk.nashorn.internal.ir.UnaryNode;
+import jdk.nashorn.internal.codegen.ObjectClassGenerator;
+import jdk.nashorn.internal.objects.Global;
+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.Property;
+import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.Source;
+import jdk.nashorn.internal.runtime.SpillProperty;
+import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
+import jdk.nashorn.internal.scripts.JD;
+import jdk.nashorn.internal.scripts.JO;
+
+import static jdk.nashorn.internal.parser.TokenType.STRING;
 
 /**
- * Parses JSON text and returns the corresponding IR node. This is derived from the objectLiteral production of the main parser.
+ * Parses JSON text and returns the corresponding IR node. This is derived from
+ * the objectLiteral production of the main parser.
  *
  * See: 15.12.1.2 The JSON Syntactic Grammar
  */
-public class JSONParser extends AbstractParser {
+public class JSONParser {
+
+    final private String source;
+    final private Global global;
+    final private boolean dualFields;
+    final int length;
+    int pos = 0;
+
+    private static final int EOF = -1;
+
+    private static final String TRUE  = "true";
+    private static final String FALSE = "false";
+    private static final String NULL  = "null";
+
+    private static final int STATE_EMPTY          = 0;
+    private static final int STATE_ELEMENT_PARSED = 1;
+    private static final int STATE_COMMA_PARSED   = 2;
 
     /**
-     * Constructor
-     * @param source  the source
-     * @param errors  the error manager
+     * Constructor.
+     *
+     * @param source     the source
+     * @param global     the global object
+     * @param dualFields whether the parser should regard dual field representation
      */
-    public JSONParser(final Source source, final ErrorManager errors) {
-        super(source, errors, false, 0);
+    public JSONParser(final String source, final Global global, final boolean dualFields) {
+        this.source = source;
+        this.global = global;
+        this.length = source.length();
+        this.dualFields = dualFields;
     }
 
     /**
-     * Implementation of the Quote(value) operation as defined in the ECMA script spec
-     * It wraps a String value in double quotes and escapes characters within in
+     * Implementation of the Quote(value) operation as defined in the ECMAscript
+     * spec. It wraps a String value in double quotes and escapes characters
+     * within.
      *
      * @param value string to quote
      *
@@ -114,329 +140,413 @@
     }
 
     /**
-     * Public parsed method - start lexing a new token stream for
-     * a JSON script
+     * Public parse method. Parse a string into a JSON object.
      *
-     * @return the JSON literal
+     * @return the parsed JSON Object
      */
-    public Node parse() {
-        stream = new TokenStream();
-
-        lexer = new Lexer(source, stream) {
-
-            @Override
-            protected boolean skipComments() {
-                return false;
-            }
-
-            @Override
-            protected boolean isStringDelimiter(final char ch) {
-                return ch == '\"';
-            }
-
-            // ECMA 15.12.1.1 The JSON Lexical Grammar - JSONWhiteSpace
-            @Override
-            protected boolean isWhitespace(final char ch) {
-                return Lexer.isJsonWhitespace(ch);
-            }
-
-            @Override
-            protected boolean isEOL(final char ch) {
-                return Lexer.isJsonEOL(ch);
-            }
-
-            // ECMA 15.12.1.1 The JSON Lexical Grammar - JSONNumber
-            @Override
-            protected void scanNumber() {
-                // Record beginning of number.
-                final int startPosition = position;
-                // Assume value is a decimal.
-                TokenType valueType = TokenType.DECIMAL;
-
-                // floating point can't start with a "." with no leading digit before
-                if (ch0 == '.') {
-                    error(Lexer.message("json.invalid.number"), STRING, position, limit);
-                }
-
-                // First digit of number.
-                final int digit = convertDigit(ch0, 10);
-
-                // skip first digit
-                skip(1);
-
-                if (digit != 0) {
-                    // Skip over remaining digits.
-                    while (convertDigit(ch0, 10) != -1) {
-                        skip(1);
-                    }
-                }
-
-                if (ch0 == '.' || ch0 == 'E' || ch0 == 'e') {
-                    // Must be a double.
-                    if (ch0 == '.') {
-                        // Skip period.
-                        skip(1);
-
-                        boolean mantissa = false;
-                        // Skip mantissa.
-                        while (convertDigit(ch0, 10) != -1) {
-                            mantissa = true;
-                            skip(1);
-                        }
-
-                        if (! mantissa) {
-                            // no digit after "."
-                            error(Lexer.message("json.invalid.number"), STRING, position, limit);
-                        }
-                    }
-
-                    // Detect exponent.
-                    if (ch0 == 'E' || ch0 == 'e') {
-                        // Skip E.
-                        skip(1);
-                        // Detect and skip exponent sign.
-                        if (ch0 == '+' || ch0 == '-') {
-                            skip(1);
-                        }
-                        boolean exponent = false;
-                        // Skip exponent.
-                        while (convertDigit(ch0, 10) != -1) {
-                            exponent = true;
-                            skip(1);
-                        }
-
-                        if (! exponent) {
-                            // no digit after "E"
-                            error(Lexer.message("json.invalid.number"), STRING, position, limit);
-                        }
-                    }
-
-                    valueType = TokenType.FLOATING;
-                }
-
-                // Add number token.
-                add(valueType, startPosition);
-            }
-
-            // ECMA 15.12.1.1 The JSON Lexical Grammar - JSONEscapeCharacter
-            @Override
-            protected boolean isEscapeCharacter(final char ch) {
-                switch (ch) {
-                    case '"':
-                    case '/':
-                    case '\\':
-                    case 'b':
-                    case 'f':
-                    case 'n':
-                    case 'r':
-                    case 't':
-                    // could be unicode escape
-                    case 'u':
-                        return true;
-                    default:
-                        return false;
-                }
-            }
-        };
-
-        k = -1;
-
-        next();
-
-        final Node resultNode = jsonLiteral();
-        expect(EOF);
-
-        return resultNode;
-    }
-
-    @SuppressWarnings("fallthrough")
-    private LiteralNode<?> getStringLiteral() {
-        final LiteralNode<?> literal = getLiteral();
-        final String         str     = (String)literal.getValue();
-
-        for (int i = 0; i < str.length(); i++) {
-            final char ch = str.charAt(i);
-            switch (ch) {
-            default:
-                if (ch > 0x001f) {
-                    break;
-                }
-            case '"':
-            case '\\':
-                throw error(AbstractParser.message("unexpected.token", str));
-            }
+    public Object parse() {
+        final Object value = parseLiteral();
+        skipWhiteSpace();
+        if (pos < length) {
+            throw expectedError(pos, "eof", toString(peek()));
         }
-
-        return literal;
+        return value;
     }
 
-    /**
-     * Parse a JSON literal from the token stream
-     * @return the JSON literal as a Node
-     */
-    private Expression jsonLiteral() {
-        final long literalToken = token;
+    private Object parseLiteral() {
+        skipWhiteSpace();
 
-        switch (type) {
-        case STRING:
-            return getStringLiteral();
-        case ESCSTRING:
-        case DECIMAL:
-        case FLOATING:
-            return getLiteral();
-        case FALSE:
-            next();
-            return LiteralNode.newInstance(literalToken, finish, false);
-        case TRUE:
-            next();
-            return LiteralNode.newInstance(literalToken, finish, true);
-        case NULL:
-            next();
-            return LiteralNode.newInstance(literalToken, finish);
-        case LBRACKET:
-            return arrayLiteral();
-        case LBRACE:
-            return objectLiteral();
-        /*
-         * A.8.1 JSON Lexical Grammar
-         *
-         * JSONNumber :: See 15.12.1.1
-         *    -opt DecimalIntegerLiteral JSONFractionopt ExponentPartopt
-         */
-        case SUB:
-            next();
-
-            final long realToken = token;
-            final Object value = getValue();
-
-            if (value instanceof Number) {
-                next();
-                return new UnaryNode(literalToken, LiteralNode.newInstance(realToken, finish, (Number)value));
-            }
-
-            throw error(AbstractParser.message("expected", "number", type.getNameOrType()));
+        final int c = peek();
+        if (c == EOF) {
+            throw expectedError(pos, "json literal", "eof");
+        }
+        switch (c) {
+        case '{':
+            return parseObject();
+        case '[':
+            return parseArray();
+        case '"':
+            return parseString();
+        case 'f':
+            return parseKeyword(FALSE, Boolean.FALSE);
+        case 't':
+            return parseKeyword(TRUE, Boolean.TRUE);
+        case 'n':
+            return parseKeyword(NULL, null);
         default:
-            break;
+            if (isDigit(c) || c == '-') {
+                return parseNumber();
+            } else if (c == '.') {
+                throw numberError(pos);
+            } else {
+                throw expectedError(pos, "json literal", toString(c));
+            }
         }
-
-        throw error(AbstractParser.message("expected", "json literal", type.getNameOrType()));
     }
 
-    /**
-     * Parse an array literal from the token stream
-     * @return the array literal as a Node
-     */
-    private LiteralNode<Expression[]> arrayLiteral() {
-        // Unlike JavaScript array literals, elison is not permitted in JSON.
+    private Object parseObject() {
+        PropertyMap propertyMap = dualFields ? JD.getInitialMap() : JO.getInitialMap();
+        ArrayData arrayData = ArrayData.EMPTY_ARRAY;
+        final ArrayList<Object> values = new ArrayList<>();
+        int state = STATE_EMPTY;
 
-        // Capture LBRACKET token.
-        final long arrayToken = token;
-        // LBRACKET tested in caller.
-        next();
+        assert peek() == '{';
+        pos++;
 
-        LiteralNode<Expression[]> result = null;
-        // Prepare to accummulating elements.
-        final List<Expression> elements = new ArrayList<>();
+        while (pos < length) {
+            skipWhiteSpace();
+            final int c = peek();
 
-loop:
-        while (true) {
-            switch (type) {
-            case RBRACKET:
-                next();
-                result = LiteralNode.newInstance(arrayToken, finish, elements);
-                break loop;
-
-            case COMMARIGHT:
-                next();
-                // check for trailing comma - not allowed in JSON
-                if (type == RBRACKET) {
-                    throw error(AbstractParser.message("trailing.comma.in.json", type.getNameOrType()));
+            switch (c) {
+            case '"':
+                if (state == STATE_ELEMENT_PARSED) {
+                    throw expectedError(pos - 1, ", or }", toString(c));
                 }
+                final String id = parseString();
+                expectColon();
+                final Object value = parseLiteral();
+                final int index = ArrayIndex.getArrayIndex(id);
+                if (ArrayIndex.isValidArrayIndex(index)) {
+                    arrayData = addArrayElement(arrayData, index, value);
+                } else {
+                    propertyMap = addObjectProperty(propertyMap, values, id, value);
+                }
+                state = STATE_ELEMENT_PARSED;
                 break;
-
-            default:
-                // Add expression element.
-                elements.add(jsonLiteral());
-                // Comma between array elements is mandatory in JSON.
-                if (type != COMMARIGHT && type != RBRACKET) {
-                   throw error(AbstractParser.message("expected", ", or ]", type.getNameOrType()));
+            case ',':
+                if (state != STATE_ELEMENT_PARSED) {
+                    throw error(AbstractParser.message("trailing.comma.in.json"), pos);
                 }
+                state = STATE_COMMA_PARSED;
+                pos++;
+                break;
+            case '}':
+                if (state == STATE_COMMA_PARSED) {
+                    throw error(AbstractParser.message("trailing.comma.in.json"), pos);
+                }
+                pos++;
+                return createObject(propertyMap, values, arrayData);
+            default:
+                throw expectedError(pos, ", or }", toString(c));
+            }
+        }
+        throw expectedError(pos, ", or }", "eof");
+    }
+
+    private static ArrayData addArrayElement(final ArrayData arrayData, final int index, final Object value) {
+        final long oldLength = arrayData.length();
+        final long longIndex = ArrayIndex.toLongIndex(index);
+        ArrayData newArrayData = arrayData;
+        if (longIndex >= oldLength) {
+            newArrayData = newArrayData.ensure(longIndex);
+            if (longIndex > oldLength) {
+                newArrayData = newArrayData.delete(oldLength, longIndex - 1);
+            }
+        }
+        return newArrayData.set(index, value, false);
+    }
+
+    private PropertyMap addObjectProperty(final PropertyMap propertyMap, final List<Object> values,
+                                                 final String id, final Object value) {
+        final Property oldProperty = propertyMap.findProperty(id);
+        final PropertyMap newMap;
+        final Class<?> type;
+        final int flags;
+        if (dualFields) {
+            type = getType(value);
+            flags = Property.DUAL_FIELDS;
+        } else {
+            type = Object.class;
+            flags = 0;
+        }
+
+        if (oldProperty != null) {
+            values.set(oldProperty.getSlot(), value);
+            newMap = propertyMap.replaceProperty(oldProperty, new SpillProperty(id, flags, oldProperty.getSlot(), type));;
+        } else {
+            values.add(value);
+            newMap = propertyMap.addProperty(new SpillProperty(id, flags, propertyMap.size(), type));
+        }
+
+        return newMap;
+    }
+
+    private Object createObject(final PropertyMap propertyMap, final List<Object> values, final ArrayData arrayData) {
+        final long[] primitiveSpill = dualFields ? new long[values.size()] : null;
+        final Object[] objectSpill = new Object[values.size()];
+
+        for (final Property property : propertyMap.getProperties()) {
+            if (!dualFields || property.getType() == Object.class) {
+                objectSpill[property.getSlot()] = values.get(property.getSlot());
+            } else {
+                primitiveSpill[property.getSlot()] = ObjectClassGenerator.pack((Number) values.get(property.getSlot()));
+            }
+        }
+
+        final ScriptObject object = dualFields ?
+                new JD(propertyMap, primitiveSpill, objectSpill) : new JO(propertyMap, null, objectSpill);
+        object.setInitialProto(global.getObjectPrototype());
+        object.setArray(arrayData);
+        return object;
+    }
+
+    private static Class<?> getType(final Object value) {
+        if (value instanceof Integer) {
+            return int.class;
+        } else if (value instanceof Long) {
+            return long.class;
+        } else if (value instanceof Double) {
+            return double.class;
+        } else {
+            return Object.class;
+        }
+    }
+
+    private void expectColon() {
+        skipWhiteSpace();
+        final int n = next();
+        if (n != ':') {
+            throw expectedError(pos - 1, ":", toString(n));
+        }
+    }
+
+    private Object parseArray() {
+        ArrayData arrayData = ArrayData.EMPTY_ARRAY;
+        int state = STATE_EMPTY;
+
+        assert peek() == '[';
+        pos++;
+
+        while (pos < length) {
+            skipWhiteSpace();
+            final int c = peek();
+
+            switch (c) {
+            case ',':
+                if (state != STATE_ELEMENT_PARSED) {
+                    throw error(AbstractParser.message("trailing.comma.in.json"), pos);
+                }
+                state = STATE_COMMA_PARSED;
+                pos++;
+                break;
+            case ']':
+                if (state == STATE_COMMA_PARSED) {
+                    throw error(AbstractParser.message("trailing.comma.in.json"), pos);
+                }
+                pos++;
+                return global.wrapAsObject(arrayData);
+            default:
+                if (state == STATE_ELEMENT_PARSED) {
+                    throw expectedError(pos, ", or ]", toString(c));
+                }
+                final long index = arrayData.length();
+                arrayData = arrayData.ensure(index).set((int) index, parseLiteral(), true);
+                state = STATE_ELEMENT_PARSED;
                 break;
             }
         }
 
-        return result;
+        throw expectedError(pos, ", or ]", "eof");
     }
 
-    /**
-     * Parse an object literal from the token stream
-     * @return the object literal as a Node
-     */
-    private ObjectNode objectLiteral() {
-        // Capture LBRACE token.
-        final long objectToken = token;
-        // LBRACE tested in caller.
-        next();
+    private String parseString() {
+        // String buffer is only instantiated if string contains escape sequences.
+        int start = ++pos;
+        StringBuilder sb = null;
 
-        // Prepare to accumulate elements.
-        final List<PropertyNode> elements = new ArrayList<>();
+        while (pos < length) {
+            final int c = next();
+            if (c <= 0x1f) {
+                // Characters < 0x1f are not allowed in JSON strings.
+                throw syntaxError(pos, "String contains control character");
 
-        // Create a block for the object literal.
-loop:
-        while (true) {
-            switch (type) {
-            case RBRACE:
-                next();
-                break loop;
-
-            case COMMARIGHT:
-                next();
-                // check for trailing comma - not allowed in JSON
-                if (type == RBRACE) {
-                    throw error(AbstractParser.message("trailing.comma.in.json", type.getNameOrType()));
+            } else if (c == '\\') {
+                if (sb == null) {
+                    sb = new StringBuilder(pos - start + 16);
                 }
-                break;
+                sb.append(source, start, pos - 1);
+                sb.append(parseEscapeSequence());
+                start = pos;
 
-            default:
-                // Get and add the next property.
-                final PropertyNode property = propertyAssignment();
-                elements.add(property);
-
-                // Comma between property assigments is mandatory in JSON.
-                if (type != RBRACE && type != COMMARIGHT) {
-                    throw error(AbstractParser.message("expected", ", or }", type.getNameOrType()));
+            } else if (c == '"') {
+                if (sb != null) {
+                    sb.append(source, start, pos - 1);
+                    return sb.toString();
                 }
-                break;
+                return source.substring(start, pos - 1);
             }
         }
 
-        // Construct new object literal.
-        return new ObjectNode(objectToken, finish, elements);
+        throw error(Lexer.message("missing.close.quote"), pos, length);
     }
 
-    /**
-     * Parse a property assignment from the token stream
-     * @return the property assignment as a Node
-     */
-    private PropertyNode propertyAssignment() {
-        // Capture firstToken.
-        final long propertyToken = token;
-        LiteralNode<?> name = null;
-
-        if (type == STRING) {
-            name = getStringLiteral();
-        } else if (type == ESCSTRING) {
-            name = getLiteral();
+    private char parseEscapeSequence() {
+        final int c = next();
+        switch (c) {
+        case '"':
+            return '"';
+        case '\\':
+            return '\\';
+        case '/':
+            return '/';
+        case 'b':
+            return '\b';
+        case 'f':
+            return '\f';
+        case 'n':
+            return '\n';
+        case 'r':
+            return '\r';
+        case 't':
+            return '\t';
+        case 'u':
+            return parseUnicodeEscape();
+        default:
+            throw error(Lexer.message("invalid.escape.char"), pos - 1, length);
         }
-
-        if (name != null) {
-            expect(COLON);
-            final Expression value = jsonLiteral();
-            return new PropertyNode(propertyToken, value.getFinish(), name, value, null, null);
-        }
-
-        // Raise an error.
-        throw error(AbstractParser.message("expected", "string", type.getNameOrType()));
     }
 
+    private char parseUnicodeEscape() {
+        return (char) (parseHexDigit() << 12 | parseHexDigit() << 8 | parseHexDigit() << 4 | parseHexDigit());
+    }
+
+    private int parseHexDigit() {
+        final int c = next();
+        if (c >= '0' && c <= '9') {
+            return c - '0';
+        } else if (c >= 'A' && c <= 'F') {
+            return c + 10 - 'A';
+        } else if (c >= 'a' && c <= 'f') {
+            return c + 10 - 'a';
+        }
+        throw error(Lexer.message("invalid.hex"), pos - 1, length);
+    }
+
+    private boolean isDigit(final int c) {
+        return c >= '0' && c <= '9';
+    }
+
+    private void skipDigits() {
+        while (pos < length) {
+            final int c = peek();
+            if (!isDigit(c)) {
+                break;
+            }
+            pos++;
+        }
+    }
+
+    private Number parseNumber() {
+        final int start = pos;
+        int c = next();
+
+        if (c == '-') {
+            c = next();
+        }
+        if (!isDigit(c)) {
+            throw numberError(start);
+        }
+        // no more digits allowed after 0
+        if (c != '0') {
+            skipDigits();
+        }
+
+        // fraction
+        if (peek() == '.') {
+            pos++;
+            if (!isDigit(next())) {
+                throw numberError(pos - 1);
+            }
+            skipDigits();
+        }
+
+        // exponent
+        c = peek();
+        if (c == 'e' || c == 'E') {
+            pos++;
+            c = next();
+            if (c == '-' || c == '+') {
+                c = next();
+            }
+            if (!isDigit(c)) {
+                throw numberError(pos - 1);
+            }
+            skipDigits();
+        }
+
+        final double d = Double.parseDouble(source.substring(start, pos));
+        if (JSType.isRepresentableAsInt(d)) {
+            return (int) d;
+        } else if (JSType.isRepresentableAsLong(d)) {
+            return (long) d;
+        }
+        return d;
+    }
+
+    private Object parseKeyword(final String keyword, final Object value) {
+        if (!source.regionMatches(pos, keyword, 0, keyword.length())) {
+            throw expectedError(pos, "json literal", "ident");
+        }
+        pos += keyword.length();
+        return value;
+    }
+
+    private int peek() {
+        if (pos >= length) {
+            return -1;
+        }
+        return source.charAt(pos);
+    }
+
+    private int next() {
+        final int next = peek();
+        pos++;
+        return next;
+    }
+
+    private void skipWhiteSpace() {
+        while (pos < length) {
+            switch (peek()) {
+            case '\t':
+            case '\r':
+            case '\n':
+            case ' ':
+                pos++;
+                break;
+            default:
+                return;
+            }
+        }
+    }
+
+    private static String toString(final int c) {
+        return c == EOF ? "eof" : String.valueOf((char) c);
+    }
+
+    ParserException error(final String message, final int start, final int length) throws ParserException {
+        final long token     = Token.toDesc(STRING, start, length);
+        final int  pos       = Token.descPosition(token);
+        final Source src     = Source.sourceFor("<json>", source);
+        final int  lineNum   = src.getLine(pos);
+        final int  columnNum = src.getColumn(pos);
+        final String formatted = ErrorManager.format(message, src, lineNum, columnNum, token);
+        return new ParserException(JSErrorType.SYNTAX_ERROR, formatted, src, lineNum, columnNum, token);
+    }
+
+    private ParserException error(final String message, final int start) {
+        return error(message, start, length);
+    }
+
+    private ParserException numberError(final int start) {
+        return error(Lexer.message("json.invalid.number"), start);
+    }
+
+    private ParserException expectedError(final int start, final String expected, final String found) {
+        return error(AbstractParser.message("expected", expected, found), start);
+    }
+
+    private ParserException syntaxError(final int start, final String reason) {
+        final String message = ECMAErrors.getMessage("syntax.error.invalid.json", reason);
+        return error(message, start);
+    }
 }
diff --git a/src/jdk/nashorn/internal/parser/Lexer.java b/src/jdk/nashorn/internal/parser/Lexer.java
index 04778cd..d1dde2e 100644
--- a/src/jdk/nashorn/internal/parser/Lexer.java
+++ b/src/jdk/nashorn/internal/parser/Lexer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -93,9 +93,6 @@
     private static final String SPACETAB = " \t";  // ASCII space and tab
     private static final String LFCR     = "\n\r"; // line feed and carriage return (ctrl-m)
 
-    private static final String JSON_WHITESPACE_EOL = LFCR;
-    private static final String JSON_WHITESPACE     = SPACETAB + LFCR;
-
     private static final String JAVASCRIPT_WHITESPACE_EOL =
         LFCR +
         "\u2028" + // line separator
@@ -385,24 +382,6 @@
     }
 
     /**
-     * Test whether a char is valid JSON whitespace
-     * @param ch a char
-     * @return true if valid JSON whitespace
-     */
-    public static boolean isJsonWhitespace(final char ch) {
-        return JSON_WHITESPACE.indexOf(ch) != -1;
-    }
-
-    /**
-     * Test whether a char is valid JSON end of line
-     * @param ch a char
-     * @return true if valid JSON end of line
-     */
-    public static boolean isJsonEOL(final char ch) {
-        return JSON_WHITESPACE_EOL.indexOf(ch) != -1;
-    }
-
-    /**
      * Test if char is a string delimiter, e.g. '\' or '"'.  Also scans exec
      * strings ('`') in scripting mode.
      * @param ch a char
@@ -1472,9 +1451,22 @@
                 skip(3);
             }
 
-            // Scan identifier.
+            // Scan identifier. It might be quoted, indicating that no string editing should take place.
+            final char quoteChar = ch0;
+            final boolean noStringEditing = quoteChar == '"' || quoteChar == '\'';
+            if (noStringEditing) {
+                skip(1);
+            }
             final int identStart = position;
             final int identLength = scanIdentifier();
+            if (noStringEditing) {
+                if (ch0 != quoteChar) {
+                    error(Lexer.message("here.non.matching.delimiter"), last, position, position);
+                    restoreState(saved);
+                    return false;
+                }
+                skip(1);
+            }
 
             // Check for identifier.
             if (identLength == 0) {
@@ -1544,7 +1536,7 @@
             }
 
             // Edit string if appropriate.
-            if (scripting && !stringState.isEmpty()) {
+            if (!noStringEditing && !stringState.isEmpty()) {
                 editString(STRING, stringState);
             } else {
                 // Add here string.
@@ -1661,9 +1653,9 @@
             //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)) {
+            if (JSType.isStrictlyRepresentableAsInt(value)) {
                 return (int)value;
-            } else if (JSType.isRepresentableAsLong(value) && !JSType.isNegativeZero(value)) {
+            } else if (JSType.isStrictlyRepresentableAsLong(value)) {
                 return (long)value;
             }
             return value;
diff --git a/src/jdk/nashorn/internal/parser/Parser.java b/src/jdk/nashorn/internal/parser/Parser.java
index 12ad59e..cfdd599 100644
--- a/src/jdk/nashorn/internal/parser/Parser.java
+++ b/src/jdk/nashorn/internal/parser/Parser.java
@@ -84,7 +84,6 @@
 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;
@@ -513,8 +512,7 @@
 
         return lc.pop(functionNode).
             setBody(lc, newBody).
-            setLastToken(lc, lastToken).
-            setState(lc, errors.hasErrors() ? CompilationState.PARSE_ERROR : CompilationState.PARSED);
+            setLastToken(lc, lastToken);
     }
 
     /**
@@ -607,7 +605,7 @@
      * @return whether the ident can be used as L-value
      */
     private static boolean checkIdentLValue(final IdentNode ident) {
-        return Token.descType(ident.getToken()).getKind() != TokenKind.KEYWORD;
+        return ident.tokenType().getKind() != TokenKind.KEYWORD;
     }
 
     /**
@@ -805,7 +803,7 @@
                                 if (!oldStrictMode && directiveStmts != null) {
                                     // check that directives preceding this one do not violate strictness
                                     for (final Node statement : directiveStmts) {
-                                        // the get value will force unescape of preceeding
+                                        // the get value will force unescape of preceding
                                         // escaped string directives
                                         getValue(statement.getToken());
                                     }
@@ -2469,7 +2467,7 @@
         //         run: function() { println("run"); }
         //     };
         //
-        // The object literal following the "new Constructor()" expresssion
+        // The object literal following the "new Constructor()" expression
         // is passed as an additional (last) argument to the constructor.
         if (!env._no_syntax_extensions && type == LBRACE) {
             arguments.add(objectLiteral());
@@ -2635,8 +2633,12 @@
             name = getIdent();
             verifyStrictIdent(name, "function name");
         } else if (isStatement) {
-            // Nashorn extension: anonymous function statements
-            if (env._no_syntax_extensions) {
+            // Nashorn extension: anonymous function statements.
+            // Do not allow anonymous function statement if extensions
+            // are now allowed. But if we are reparsing then anon function
+            // statement is possible - because it was used as function
+            // expression in surrounding code.
+            if (env._no_syntax_extensions && reparsedFunction == null) {
                 expect(IDENT);
             }
         }
@@ -2716,6 +2718,11 @@
         }
 
         if (isStatement) {
+            if (isAnonymous) {
+                appendStatement(new ExpressionStatement(functionLine, functionToken, finish, functionNode));
+                return functionNode;
+            }
+
             final int     varFlags = (topLevel || !useBlockScope()) ? 0 : VarNode.IS_LET;
             final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, functionNode, varFlags);
             if (topLevel) {
diff --git a/src/jdk/nashorn/internal/parser/TokenType.java b/src/jdk/nashorn/internal/parser/TokenType.java
index 36d1ecd..7201eb8 100644
--- a/src/jdk/nashorn/internal/parser/TokenType.java
+++ b/src/jdk/nashorn/internal/parser/TokenType.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -222,9 +222,11 @@
 
     /**
      * Determines if the token has greater precedence than other.
+     *
      * @param other  Compare token.
      * @param isLeft Is to the left of the other.
-     * @return True if greater precedence.
+     *
+     * @return {@code true} if greater precedence.
      */
     public boolean needsParens(final TokenType other, final boolean isLeft) {
         return other.precedence != 0 &&
@@ -234,16 +236,16 @@
 
     /**
      * Determines if the type is a valid operator.
-     * @param noIn TRUE if IN operator should be ignored.
-     * @return TRUE if valid operator.
+     *
+     * @param noIn {@code true} if IN operator should be ignored.
+     *
+     * @return {@code true} if valid operator.
      */
     public boolean isOperator(final boolean noIn) {
         return kind == BINARY && (!noIn || this != IN) && precedence != 0;
     }
 
-    /**
-     * Accessors.
-     */
+
     public int getLength() {
         assert name != null : "Token name not set";
         return name.length();
diff --git a/src/jdk/nashorn/internal/runtime/AccessorProperty.java b/src/jdk/nashorn/internal/runtime/AccessorProperty.java
index a9afeb9..6fde66b 100644
--- a/src/jdk/nashorn/internal/runtime/AccessorProperty.java
+++ b/src/jdk/nashorn/internal/runtime/AccessorProperty.java
@@ -25,7 +25,6 @@
 
 package jdk.nashorn.internal.runtime;
 
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
 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.createSetter;
@@ -98,7 +97,7 @@
                 objectSetters[i] = MH.asType(MH.setter(LOOKUP, structure, fieldName, typeClass), Lookup.SET_OBJECT_TYPE);
             }
 
-            if (!OBJECT_FIELDS_ONLY) {
+            if (!StructureLoader.isSingleFieldStructure(structure.getName())) {
                 for (int i = 0; i < fieldCount; i++) {
                     final String fieldNamePrimitive = getFieldName(i, PRIMITIVE_FIELD_TYPE);
                     final Class<?> typeClass = PRIMITIVE_FIELD_TYPE.getTypeClass();
@@ -211,7 +210,7 @@
      * @param setter the property setter or null if non writable, non configurable
      */
     private AccessorProperty(final String key, final int flags, final int slot, final MethodHandle getter, final MethodHandle setter) {
-        super(key, flags | IS_BUILTIN | (getter.type().returnType().isPrimitive() ? IS_NASGEN_PRIMITIVE : 0), slot);
+        super(key, flags | IS_BUILTIN | DUAL_FIELDS | (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
@@ -221,18 +220,15 @@
         final Class<?> setterType = setter == null ? null : setter.type().parameterType(1);
 
         assert setterType == null || setterType == getterType;
-        if (OBJECT_FIELDS_ONLY) {
-            primitiveGetter = primitiveSetter = null;
+
+        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 {
-            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;
-            }
+            primitiveGetter = primitiveSetter = null;
         }
 
         assert primitiveGetter == null || primitiveGetter.type() == Lookup.GET_PRIMITIVE_TYPE : primitiveGetter + "!=" + Lookup.GET_PRIMITIVE_TYPE;
@@ -241,7 +237,7 @@
         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;
 
-        setType(OBJECT_FIELDS_ONLY ? Object.class : getterType);
+        setType(getterType);
     }
 
     /**
@@ -282,6 +278,9 @@
             objectSetter    = gs.objectSetters[slot];
             primitiveSetter = gs.primitiveSetters[slot];
         }
+
+        // Always use dual fields except for single field structures
+        assert hasDualFields() != StructureLoader.isSingleFieldStructure(structure.getName());
     }
 
     /**
@@ -310,7 +309,7 @@
      */
     public AccessorProperty(final String key, final int flags, final Class<?> structure, final int slot, final Class<?> initialType) {
         this(key, flags, structure, slot);
-        setType(OBJECT_FIELDS_ONLY ? Object.class : initialType);
+        setType(hasDualFields() ? initialType : Object.class);
     }
 
     /**
@@ -347,7 +346,7 @@
      * @param initialValue initial value
      */
     protected final void setInitialValue(final ScriptObject owner, final Object initialValue) {
-        setType(JSType.unboxedFieldType(initialValue));
+        setType(hasDualFields() ? JSType.unboxedFieldType(initialValue) : Object.class);
         if (initialValue instanceof Integer) {
             invokeSetter(owner, ((Integer)initialValue).intValue());
         } else if (initialValue instanceof Long) {
@@ -363,7 +362,7 @@
      * Initialize the type of a property
      */
     protected final void initializeType() {
-        setType(OBJECT_FIELDS_ONLY ? Object.class : null);
+        setType(!hasDualFields() ? Object.class : null);
     }
 
     private void readObject(final ObjectInputStream s) throws IOException, ClassNotFoundException {
@@ -670,7 +669,7 @@
 
     @Override
     public final boolean canChangeType() {
-        if (OBJECT_FIELDS_ONLY) {
+        if (!hasDualFields()) {
             return false;
         }
         // Return true for currently undefined even if non-writable/configurable to allow initialization of ES6 CONST.
diff --git a/src/jdk/nashorn/internal/runtime/AllocationStrategy.java b/src/jdk/nashorn/internal/runtime/AllocationStrategy.java
index e4d6ccb..5c4c03f 100644
--- a/src/jdk/nashorn/internal/runtime/AllocationStrategy.java
+++ b/src/jdk/nashorn/internal/runtime/AllocationStrategy.java
@@ -29,55 +29,99 @@
 import java.io.Serializable;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
+import java.lang.ref.WeakReference;
+import jdk.nashorn.internal.codegen.Compiler;
 import jdk.nashorn.internal.codegen.CompilerConstants;
-import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor;
+import jdk.nashorn.internal.codegen.ObjectClassGenerator;
 
 /**
- * Encapsulates the allocation strategy for a function when used as a constructor. Basically the same as
- * {@link AllocatorDescriptor}, but with an additionally cached resolved method handle. There is also a
- * canonical default allocation strategy for functions that don't assign any "this" properties (vast majority
- * of all functions), therefore saving some storage space in {@link RecompilableScriptFunctionData} that would
- * otherwise be lost to identical tuples of (map, className, handle) fields.
+ * Encapsulates the allocation strategy for a function when used as a constructor.
  */
-final class AllocationStrategy implements Serializable {
+final public class AllocationStrategy implements Serializable {
     private static final long serialVersionUID = 1L;
 
     private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
 
-    private static final AllocationStrategy DEFAULT_STRATEGY = new AllocationStrategy(new AllocatorDescriptor(0));
+    /** Number of fields in the allocated object */
+    private final int fieldCount;
 
-    /** Allocator map from allocator descriptor */
-    private final PropertyMap allocatorMap;
+    /** Whether to use dual field representation */
+    private final boolean dualFields;
 
     /** Name of class where allocator function resides */
-    private final String allocatorClassName;
+    private transient String allocatorClassName;
 
     /** lazily generated allocator */
     private transient MethodHandle allocator;
 
-    private AllocationStrategy(final AllocatorDescriptor desc) {
-        this.allocatorMap = desc.getAllocatorMap();
-        // These classes get loaded, so an interned variant of their name is most likely around anyway.
-        this.allocatorClassName = desc.getAllocatorClassName().intern();
+    /** Last used allocator map */
+    private transient AllocatorMap lastMap;
+
+    /**
+     * Construct an allocation strategy with the given map and class name.
+     * @param fieldCount number of fields in the allocated object
+     * @param dualFields whether to use dual field representation
+     */
+    public AllocationStrategy(final int fieldCount, final boolean dualFields) {
+        this.fieldCount = fieldCount;
+        this.dualFields = dualFields;
     }
 
-    private boolean matches(final AllocatorDescriptor desc) {
-        return desc.getAllocatorMap().size() == allocatorMap.size() &&
-                desc.getAllocatorClassName().equals(allocatorClassName);
+    private String getAllocatorClassName() {
+        if (allocatorClassName == null) {
+            // These classes get loaded, so an interned variant of their name is most likely around anyway.
+            allocatorClassName = Compiler.binaryName(ObjectClassGenerator.getClassName(fieldCount, dualFields)).intern();
+        }
+        return allocatorClassName;
     }
 
-    static AllocationStrategy get(final AllocatorDescriptor desc) {
-        return DEFAULT_STRATEGY.matches(desc) ? DEFAULT_STRATEGY : new AllocationStrategy(desc);
-    }
+    /**
+     * Get the property map for the allocated object.
+     * @param prototype the prototype object
+     * @return the property map
+     */
+    synchronized PropertyMap getAllocatorMap(final ScriptObject prototype) {
+        assert prototype != null;
+        final PropertyMap protoMap = prototype.getMap();
 
-    PropertyMap getAllocatorMap() {
+        if (lastMap != null) {
+            if (!lastMap.hasSharedProtoMap()) {
+                if (lastMap.hasSamePrototype(prototype)) {
+                    return lastMap.allocatorMap;
+                }
+                if (lastMap.hasSameProtoMap(protoMap) && lastMap.hasUnchangedProtoMap()) {
+                    // Convert to shared prototype map. Allocated objects will use the same property map
+                    // that can be used as long as none of the prototypes modify the shared proto map.
+                    final PropertyMap allocatorMap = PropertyMap.newMap(null, getAllocatorClassName(), 0, fieldCount, 0);
+                    final SharedPropertyMap sharedProtoMap = new SharedPropertyMap(protoMap);
+                    allocatorMap.setSharedProtoMap(sharedProtoMap);
+                    prototype.setMap(sharedProtoMap);
+                    lastMap = new AllocatorMap(prototype, protoMap, allocatorMap);
+                    return allocatorMap;
+                }
+            }
+
+            if (lastMap.hasValidSharedProtoMap() && lastMap.hasSameProtoMap(protoMap)) {
+                prototype.setMap(lastMap.getSharedProtoMap());
+                return lastMap.allocatorMap;
+            }
+        }
+
+        final PropertyMap allocatorMap = PropertyMap.newMap(null, getAllocatorClassName(), 0, fieldCount, 0);
+        lastMap = new AllocatorMap(prototype, protoMap, allocatorMap);
+
         return allocatorMap;
     }
 
+    /**
+     * Allocate an object with the given property map
+     * @param map the property map
+     * @return the allocated object
+     */
     ScriptObject allocate(final PropertyMap map) {
         try {
             if (allocator == null) {
-                allocator = MH.findStatic(LOOKUP, Context.forStructureClass(allocatorClassName),
+                allocator = MH.findStatic(LOOKUP, Context.forStructureClass(getAllocatorClassName()),
                         CompilerConstants.ALLOCATE.symbolName(), MH.type(ScriptObject.class, PropertyMap.class));
             }
             return (ScriptObject)allocator.invokeExact(map);
@@ -88,17 +132,47 @@
         }
     }
 
-    private Object readResolve() {
-        if(allocatorMap.size() == DEFAULT_STRATEGY.allocatorMap.size() &&
-                allocatorClassName.equals(DEFAULT_STRATEGY.allocatorClassName)) {
-            return DEFAULT_STRATEGY;
-        }
-        return this;
-    }
-
     @Override
     public String toString() {
-        return "AllocationStrategy[allocatorClassName=" + allocatorClassName + ", allocatorMap.size=" +
-                allocatorMap.size() + "]";
+        return "AllocationStrategy[fieldCount=" + fieldCount + "]";
+    }
+
+    static class AllocatorMap {
+        final private WeakReference<ScriptObject> prototype;
+        final private WeakReference<PropertyMap> prototypeMap;
+
+        private PropertyMap allocatorMap;
+
+        AllocatorMap(final ScriptObject prototype, final PropertyMap protoMap, final PropertyMap allocMap) {
+            this.prototype = new WeakReference<>(prototype);
+            this.prototypeMap = new WeakReference<>(protoMap);
+            this.allocatorMap = allocMap;
+        }
+
+        boolean hasSamePrototype(final ScriptObject proto) {
+            return prototype.get() == proto;
+        }
+
+        boolean hasSameProtoMap(final PropertyMap protoMap) {
+            return prototypeMap.get() == protoMap || allocatorMap.getSharedProtoMap() == protoMap;
+        }
+
+        boolean hasUnchangedProtoMap() {
+            final ScriptObject proto = prototype.get();
+            return proto != null && proto.getMap() == prototypeMap.get();
+        }
+
+        boolean hasSharedProtoMap() {
+            return getSharedProtoMap() != null;
+        }
+
+        boolean hasValidSharedProtoMap() {
+            return hasSharedProtoMap() && getSharedProtoMap().isValidSharedProtoMap();
+        }
+
+        PropertyMap getSharedProtoMap() {
+            return allocatorMap.getSharedProtoMap();
+        }
+
     }
 }
diff --git a/src/jdk/nashorn/internal/codegen/AstSerializer.java b/src/jdk/nashorn/internal/runtime/AstSerializer.java
similarity index 73%
rename from src/jdk/nashorn/internal/codegen/AstSerializer.java
rename to src/jdk/nashorn/internal/runtime/AstSerializer.java
index dc35f96..35036d8 100644
--- a/src/jdk/nashorn/internal/codegen/AstSerializer.java
+++ b/src/jdk/nashorn/internal/runtime/AstSerializer.java
@@ -22,20 +22,14 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package jdk.nashorn.internal.codegen;
+package jdk.nashorn.internal.runtime;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.ObjectOutputStream;
-import java.util.Collections;
 import java.util.zip.Deflater;
 import java.util.zip.DeflaterOutputStream;
-import jdk.nashorn.internal.ir.Block;
 import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.LexicalContext;
-import jdk.nashorn.internal.ir.Node;
-import jdk.nashorn.internal.ir.Statement;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 import jdk.nashorn.internal.runtime.options.Options;
 
 /**
@@ -50,7 +44,7 @@
         final ByteArrayOutputStream out = new ByteArrayOutputStream();
         final Deflater deflater = new Deflater(COMPRESSION_LEVEL);
         try (final ObjectOutputStream oout = new ObjectOutputStream(new DeflaterOutputStream(out, deflater))) {
-            oout.writeObject(removeInnerFunctionBodies(fn));
+            oout.writeObject(fn);
         } catch (final IOException e) {
             throw new AssertionError("Unexpected exception serializing function", e);
         } finally {
@@ -58,16 +52,4 @@
         }
         return out.toByteArray();
     }
-
-    private static FunctionNode removeInnerFunctionBodies(final FunctionNode fn) {
-        return (FunctionNode)fn.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
-            @Override
-            public Node leaveBlock(final Block block) {
-                if (lc.isFunctionBody() && lc.getFunction(block) != lc.getOutermostFunction()) {
-                    return block.setStatements(lc, Collections.<Statement>emptyList());
-                }
-                return super.leaveBlock(block);
-            }
-        });
-    }
 }
diff --git a/src/jdk/nashorn/internal/runtime/CodeInstaller.java b/src/jdk/nashorn/internal/runtime/CodeInstaller.java
index e2b5afe..dc6ed09 100644
--- a/src/jdk/nashorn/internal/runtime/CodeInstaller.java
+++ b/src/jdk/nashorn/internal/runtime/CodeInstaller.java
@@ -38,15 +38,14 @@
  * The compiler still retains most of the state around code emission
  * and management internally, so this is to avoid passing around any
  * logic that isn't directly related to installing a class
- * @param <T> owner class type for this code installer
  *
  */
-public interface CodeInstaller<T> {
+public interface CodeInstaller {
     /**
-     * Return the owner for the CodeInstaller, e.g. a {@link Context}
-     * @return owner
+     * Return the {@link Context} associated with this code installer.
+     * @return the context.
      */
-    public T getOwner();
+    public Context getContext();
 
     /**
      * Install a class.
@@ -86,7 +85,7 @@
      * @param source the script source
      * @param mainClassName the main class name
      * @param classBytes map of class names to class bytes
-     * @param initializers compilation id -> FunctionInitializer map
+     * @param initializers compilation id -&gt; FunctionInitializer map
      * @param constants constants array
      * @param compilationId compilation id
      */
@@ -106,7 +105,7 @@
      * new, independent class loader.
      * @return a new code installer with a new independent class loader.
      */
-    public CodeInstaller<T> withNewLoader();
+    public CodeInstaller withNewLoader();
 
     /**
      * Returns true if this code installer is compatible with the other code installer. Compatibility is expected to be
@@ -115,6 +114,6 @@
      * @param other the other code installer tested for compatibility with this code installer.
      * @return true if this code installer is compatible with the other code installer.
      */
-    public boolean isCompatibleWith(CodeInstaller<T> other);
+    public boolean isCompatibleWith(CodeInstaller other);
 
 }
diff --git a/src/jdk/nashorn/internal/runtime/CodeStore.java b/src/jdk/nashorn/internal/runtime/CodeStore.java
index 4e745ff..b7194c6 100644
--- a/src/jdk/nashorn/internal/runtime/CodeStore.java
+++ b/src/jdk/nashorn/internal/runtime/CodeStore.java
@@ -189,7 +189,7 @@
      * @param paramTypes parameter types
      * @return a string representing the function
      */
-    public static String getCacheKey(final int functionId, final Type[] paramTypes) {
+    public static String getCacheKey(final Object functionId, final Type[] paramTypes) {
         final StringBuilder b = new StringBuilder().append(functionId);
         if(paramTypes != null && paramTypes.length > 0) {
             b.append('-');
@@ -275,7 +275,7 @@
 
         @Override
         public StoredScript load(final Source source, final String functionKey) {
-            if (source.getLength() < minSize) {
+            if (belowThreshold(source)) {
                 return null;
             }
 
diff --git a/src/jdk/nashorn/internal/runtime/CompiledFunction.java b/src/jdk/nashorn/internal/runtime/CompiledFunction.java
index ce20ed3..63889cc 100644
--- a/src/jdk/nashorn/internal/runtime/CompiledFunction.java
+++ b/src/jdk/nashorn/internal/runtime/CompiledFunction.java
@@ -27,6 +27,7 @@
 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;
@@ -101,7 +102,7 @@
             /*
              * An optimistic builtin with isOptimistic=true works like any optimistic generated function, i.e. it
              * can throw unwarranted optimism exceptions. As native functions trivially can't have parts of them
-             * regenerated as restof methods, this only works if the methods are atomic/functional in their behavior
+             * regenerated as "restOf" methods, this only works if the methods are atomic/functional in their behavior
              * and doesn't modify state before an UOE can be thrown. If they aren't, we can reexecute a wider version
              * of the same builtin in a recompilation handler for FinalScriptFunctionData. There are several
              * candidate methods in Native* that would benefit from this, but I haven't had time to implement any
@@ -528,8 +529,9 @@
 
         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) {
+        // We must match all incoming parameters, including "this". "this" will usually be Object, but there
+        // are exceptions, e.g. when calling functions with primitive "this" in strict mode or through call/apply.
+        for(int i = 0; i < minParams; ++i) {
             final Type fnType = Type.typeFor(type.parameterType(i + thisThisIndex));
             final Type csType = csIsVarArg ? Type.OBJECT : Type.typeFor(other.parameterType(i + 1));
             if(!fnType.isEquivalentTo(csType)) {
@@ -565,7 +567,7 @@
             return handle;
         }
 
-        // Otherwise, we need a new level of indirection; need to introduce a mutable call site that can relink itslef
+        // Otherwise, we need a new level of indirection; need to introduce a mutable call site that can relink itself
         // to the compiled function's changed target whenever the optimistic assumptions are invalidated.
         final CallSite cs = new MutableCallSite(handle.type());
         relinkComposableInvoker(cs, this, isConstructor);
@@ -819,7 +821,7 @@
         // 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 boolean serialized = effectiveOptInfo.isSerialized();
+        final boolean cached = fn.isCached();
         final Compiler compiler = effectiveOptInfo.getCompiler(fn, ct, re); //set to non rest-of
 
         if (!shouldRecompile) {
@@ -827,11 +829,11 @@
             // 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, ct, effectiveOptInfo.invalidatedProgramPoints);
-            return restOfHandle(effectiveOptInfo, compiler.compile(fn, serialized ? CompilationPhases.COMPILE_SERIALIZED_RESTOF : CompilationPhases.COMPILE_ALL_RESTOF), currentOptInfo != null);
+            return restOfHandle(effectiveOptInfo, compiler.compile(fn, cached ? CompilationPhases.COMPILE_CACHED_RESTOF : CompilationPhases.COMPILE_ALL_RESTOF), currentOptInfo != null);
         }
 
         logRecompile("Deoptimizing recompilation (up to bytecode) ", fn, ct, effectiveOptInfo.invalidatedProgramPoints);
-        fn = compiler.compile(fn, serialized ? CompilationPhases.RECOMPILE_SERIALIZED_UPTO_BYTECODE : CompilationPhases.COMPILE_UPTO_BYTECODE);
+        fn = compiler.compile(fn, cached ? CompilationPhases.RECOMPILE_CACHED_UPTO_BYTECODE : CompilationPhases.COMPILE_UPTO_BYTECODE);
         log.fine("Reusable IR generated");
 
         // compile the rest of the function, and install it
@@ -955,10 +957,6 @@
         FunctionNode reparse() {
             return data.reparse();
         }
-
-        boolean isSerialized() {
-            return data.isSerialized();
-        }
     }
 
     @SuppressWarnings("unused")
diff --git a/src/jdk/nashorn/internal/runtime/ConsString.java b/src/jdk/nashorn/internal/runtime/ConsString.java
index a181b0c..2c6bece 100644
--- a/src/jdk/nashorn/internal/runtime/ConsString.java
+++ b/src/jdk/nashorn/internal/runtime/ConsString.java
@@ -25,6 +25,8 @@
 
 package jdk.nashorn.internal.runtime;
 
+import static jdk.nashorn.internal.runtime.JSType.isString;
+
 import java.util.ArrayDeque;
 import java.util.Deque;
 
@@ -52,8 +54,8 @@
      * @param right right char sequence
      */
     public ConsString(final CharSequence left, final CharSequence right) {
-        assert left instanceof String || left instanceof ConsString;
-        assert right instanceof String || right instanceof ConsString;
+        assert isString(left);
+        assert isString(right);
         this.left = left;
         this.right = right;
         length = left.length() + right.length();
diff --git a/src/jdk/nashorn/internal/runtime/Context.java b/src/jdk/nashorn/internal/runtime/Context.java
index 9e85199..0d82136 100644
--- a/src/jdk/nashorn/internal/runtime/Context.java
+++ b/src/jdk/nashorn/internal/runtime/Context.java
@@ -60,11 +60,13 @@
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
 import java.util.logging.Level;
+import javax.script.ScriptContext;
 import javax.script.ScriptEngine;
 import jdk.internal.org.objectweb.asm.ClassReader;
 import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
@@ -130,11 +132,28 @@
     private static MethodType CREATE_PROGRAM_FUNCTION_TYPE = MethodType.methodType(ScriptFunction.class, ScriptObject.class);
 
     /**
+     * Should scripts use only object slots for fields, or dual long/object slots? The default
+     * behaviour is to couple this to optimistic types, using dual representation if optimistic types are enabled
+     * and single field representation otherwise. This can be overridden by setting either the "nashorn.fields.objects"
+     * or "nashorn.fields.dual" system property.
+     */
+    private final FieldMode fieldMode;
+
+    private static enum FieldMode {
+        /** Value for automatic field representation depending on optimistic types setting */
+        AUTO,
+        /** Value for object field representation regardless of optimistic types setting */
+        OBJECTS,
+        /** Value for dual primitive/object field representation regardless of optimistic types setting */
+        DUAL
+    }
+
+    /**
      * Keeps track of which builtin prototypes and properties have been relinked
      * Currently we are conservative and associate the name of a builtin class with all
      * its properties, so it's enough to invalidate a property to break all assumptions
      * about a prototype. This can be changed to a more fine grained approach, but no one
-     * ever needs this, given the very rare occurance of swapping out only parts of
+     * ever needs this, given the very rare occurrence of swapping out only parts of
      * a builtin v.s. the entire builtin object
      */
     private final Map<String, SwitchPoint> builtinSwitchPoints = new HashMap<>();
@@ -148,7 +167,7 @@
      * ContextCodeInstaller that has the privilege of installing classes in the Context.
      * Can only be instantiated from inside the context and is opaque to other classes
      */
-    public static class ContextCodeInstaller implements CodeInstaller<ScriptEnvironment> {
+    public static class ContextCodeInstaller implements CodeInstaller {
         private final Context      context;
         private final ScriptLoader loader;
         private final CodeSource   codeSource;
@@ -166,13 +185,9 @@
             this.codeSource = codeSource;
         }
 
-        /**
-         * Return the script environment for this installer
-         * @return ScriptEnvironment
-         */
         @Override
-        public ScriptEnvironment getOwner() {
-            return context.env;
+        public Context getContext() {
+            return context;
         }
 
         @Override
@@ -235,7 +250,7 @@
         }
 
         @Override
-        public CodeInstaller<ScriptEnvironment> withNewLoader() {
+        public CodeInstaller withNewLoader() {
             // Reuse this installer if we're within our limits.
             if (usageCount < MAX_USAGES && bytesDefined < MAX_BYTES_DEFINED) {
                 return this;
@@ -244,7 +259,7 @@
         }
 
         @Override
-        public boolean isCompatibleWith(final CodeInstaller<ScriptEnvironment> other) {
+        public boolean isCompatibleWith(final CodeInstaller other) {
             if (other instanceof ContextCodeInstaller) {
                 final ContextCodeInstaller cci = (ContextCodeInstaller)other;
                 return cci.context == context && cci.codeSource == codeSource;
@@ -433,7 +448,7 @@
      * @param appLoader application class loader
      */
     public Context(final Options options, final ErrorManager errors, final ClassLoader appLoader) {
-        this(options, errors, appLoader, (ClassFilter)null);
+        this(options, errors, appLoader, null);
     }
 
     /**
@@ -521,6 +536,14 @@
             getErr().println("nashorn full version " + Version.fullVersion());
         }
 
+        if (Options.getBooleanProperty("nashorn.fields.dual")) {
+            fieldMode = FieldMode.DUAL;
+        } else if (Options.getBooleanProperty("nashorn.fields.objects")) {
+            fieldMode = FieldMode.OBJECTS;
+        } else {
+            fieldMode = FieldMode.AUTO;
+        }
+
         initLoggers();
     }
 
@@ -575,6 +598,14 @@
     }
 
     /**
+     * Should scripts compiled by this context use dual field representation?
+     * @return true if using dual fields, false for object-only fields
+     */
+    public boolean useDualFields() {
+        return fieldMode == FieldMode.DUAL || (fieldMode == FieldMode.AUTO && env._optimistic_types);
+    }
+
+    /**
      * Get the PropertyMap of the current global scope
      * @return the property map of the current global scope
      */
@@ -633,12 +664,11 @@
      * @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?
      * @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);
+            final Object callThis, final Object location) {
+        return eval(initialScope, string, callThis, location, false, false);
     }
 
     /**
@@ -657,14 +687,16 @@
             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?
+        // is this direct 'eval' builtin call?
+        final boolean directEval = evalCall && (location != UNDEFINED);
         final Global  global = Context.getGlobal();
         ScriptObject scope = initialScope;
 
         // ECMA section 10.1.1 point 2 says eval code is strict if it begins
         // with "use strict" directive or eval direct call itself is made
         // from from strict mode code. We are passed with caller's strict mode.
-        boolean strictFlag = directEval && strict;
+        // Nashorn extension: any 'eval' is unconditionally strict when -strict is specified.
+        boolean strictFlag = strict || this._strict;
 
         Class<?> clazz = null;
         try {
@@ -688,29 +720,26 @@
         // In strict mode, eval does not instantiate variables and functions
         // in the caller's environment. A new environment is created!
         if (strictFlag) {
-            // Create a new scope object
-            final ScriptObject strictEvalScope = global.newObject();
-
-            // bless it as a "scope"
-            strictEvalScope.setIsScope();
-
-            // set given scope to be it's proto so that eval can still
-            // access caller environment vars in the new environment.
-            strictEvalScope.setProto(scope);
-            scope = strictEvalScope;
+            // Create a new scope object with given scope as its prototype
+            scope = newScope(scope);
         }
 
         final ScriptFunction func = getProgramFunction(clazz, scope);
         Object evalThis;
         if (directEval) {
-            evalThis = callThis instanceof ScriptObject || strictFlag ? callThis : global;
+            evalThis = (callThis != UNDEFINED && callThis != null) || strictFlag ? callThis : global;
         } else {
-            evalThis = global;
+            // either indirect evalCall or non-eval (Function, engine.eval, ScriptObjectMirror.eval..)
+            evalThis = callThis;
         }
 
         return ScriptRuntime.apply(func, evalThis);
     }
 
+    private static ScriptObject newScope(final ScriptObject callerScope) {
+        return new Scope(callerScope, PropertyMap.newMap(Scope.class));
+    }
+
     private static Source loadInternal(final String srcStr, final String prefix, final String resourcePath) {
         if (srcStr.startsWith(prefix)) {
             final String resource = resourcePath + srcStr.substring(prefix.length());
@@ -744,7 +773,7 @@
      *
      * @throws IOException if source cannot be found or loaded
      */
-    public Object load(final ScriptObject scope, final Object from) throws IOException {
+    public Object load(final Object scope, final Object from) throws IOException {
         final Object src = from instanceof ConsString ? from.toString() : from;
         Source source = null;
 
@@ -796,7 +825,42 @@
         }
 
         if (source != null) {
-            return evaluateSource(source, scope, scope);
+            if (scope instanceof ScriptObject && ((ScriptObject)scope).isScope()) {
+                final ScriptObject sobj = (ScriptObject)scope;
+                // passed object is a script object
+                // Global is the only user accessible scope ScriptObject
+                assert sobj.isGlobal() : "non-Global scope object!!";
+                return evaluateSource(source, sobj, sobj);
+            } else if (scope == null || scope == UNDEFINED) {
+                // undefined or null scope. Use current global instance.
+                final Global global = getGlobal();
+                return evaluateSource(source, global, global);
+            } else {
+                /*
+                 * Arbitrary object passed for scope.
+                 * Indirect load that is equivalent to:
+                 *
+                 *    (function(scope, source) {
+                 *        with (scope) {
+                 *            eval(<script_from_source>);
+                 *        }
+                 *    })(scope, source);
+                 */
+                final Global global = getGlobal();
+                // Create a new object. This is where all declarations
+                // (var, function) from the evaluated code go.
+                // make global to be its __proto__ so that global
+                // definitions are accessible to the evaluated code.
+                final ScriptObject evalScope = newScope(global);
+
+                // finally, make a WithObject around user supplied scope object
+                // so that it's properties are accessible as variables.
+                final ScriptObject withObj = ScriptRuntime.openWith(evalScope, scope);
+
+                // evaluate given source with 'withObj' as scope
+                // but use global object as "this".
+                return evaluateSource(source, withObj, global);
+            }
         }
 
         throw typeError("cant.load.script", ScriptRuntime.safeToString(from));
@@ -904,7 +968,7 @@
      * @throw SecurityException if not accessible
      */
     private static void checkPackageAccess(final SecurityManager sm, final String fullName) {
-        sm.getClass(); // null check
+        Objects.requireNonNull(sm);
         final int index = fullName.lastIndexOf('.');
         if (index != -1) {
             final String pkgName = fullName.substring(0, index);
@@ -919,6 +983,16 @@
     }
 
     /**
+     * Is {@code className} the name of a structure class?
+     *
+     * @param className a class name
+     * @return true if className is a structure class name
+     */
+    public static boolean isStructureClass(final String className) {
+        return StructureLoader.isStructureClass(className);
+    }
+
+    /**
      * Checks that the given Class can be accessed from no permissions context.
      *
      * @param clazz Class object
@@ -1194,16 +1268,21 @@
 
         StoredScript storedScript = null;
         FunctionNode functionNode = null;
-        // We only use the code store here if optimistic types are disabled. With optimistic types, initial compilation
-        // just creates a thin wrapper, and actual code is stored per function in RecompilableScriptFunctionData.
-        final boolean useCodeStore = codeStore != null && !env._parse_only && !env._optimistic_types;
-        final String cacheKey = useCodeStore ? CodeStore.getCacheKey(0, null) : null;
+        // Don't use code store if optimistic types is enabled but lazy compilation is not.
+        // This would store a full script compilation with many wrong optimistic assumptions that would
+        // do more harm than good on later runs with both optimistic types and lazy compilation enabled.
+        final boolean useCodeStore = codeStore != null && !env._parse_only && (!env._optimistic_types || env._lazy_compilation);
+        final String cacheKey = useCodeStore ? CodeStore.getCacheKey("script", null) : null;
 
         if (useCodeStore) {
             storedScript = codeStore.load(source, cacheKey);
         }
 
         if (storedScript == null) {
+            if (env._dest_dir != null) {
+                source.dump(env._dest_dir);
+            }
+
             functionNode = new Parser(env, source, errMan, strict, getLogger(Parser.class)).parse();
 
             if (errMan.hasErrors()) {
@@ -1226,14 +1305,12 @@
         final URL          url    = source.getURL();
         final ScriptLoader loader = env._loader_per_compile ? createNewLoader() : scriptLoader;
         final CodeSource   cs     = new CodeSource(url, (CodeSigner[])null);
-        final CodeInstaller<ScriptEnvironment> installer = new ContextCodeInstaller(this, loader, cs);
+        final CodeInstaller installer = new ContextCodeInstaller(this, loader, cs);
 
         if (storedScript == null) {
             final CompilationPhases phases = Compiler.CompilationPhases.COMPILE_ALL;
 
-            final Compiler compiler = new Compiler(
-                    this,
-                    env,
+            final Compiler compiler = Compiler.forInitialCompilation(
                     installer,
                     source,
                     errMan,
@@ -1247,7 +1324,7 @@
             compiler.persistClassInfo(cacheKey, compiledFunction);
         } else {
             Compiler.updateCompilationId(storedScript.getCompilationId());
-            script = install(storedScript, source, installer);
+            script = storedScript.installScript(source, installer);
         }
 
         cacheClass(source, script);
@@ -1269,51 +1346,6 @@
     }
 
     /**
-     * Install a previously compiled class from the code cache.
-     *
-     * @param storedScript cached script containing class bytes and constants
-     * @return main script class
-     */
-    private static Class<?> install(final StoredScript storedScript, final Source source, final CodeInstaller<ScriptEnvironment> installer) {
-
-        final Map<String, Class<?>> installedClasses = new HashMap<>();
-        final Map<String, byte[]>   classBytes       = storedScript.getClassBytes();
-        final Object[] constants       = storedScript.getConstants();
-        final String   mainClassName   = storedScript.getMainClassName();
-        final byte[]   mainClassBytes  = classBytes.get(mainClassName);
-        final Class<?> mainClass       = installer.install(mainClassName, mainClassBytes);
-        final Map<Integer, FunctionInitializer> initializers = storedScript.getInitializers();
-
-        installedClasses.put(mainClassName, mainClass);
-
-        for (final Map.Entry<String, byte[]> entry : classBytes.entrySet()) {
-            final String className = entry.getKey();
-            if (className.equals(mainClassName)) {
-                continue;
-            }
-            final byte[] code = entry.getValue();
-
-            installedClasses.put(className, installer.install(className, code));
-        }
-
-        installer.initialize(installedClasses.values(), source, constants);
-
-        for (final Object constant : constants) {
-            if (constant instanceof RecompilableScriptFunctionData) {
-                final RecompilableScriptFunctionData data = (RecompilableScriptFunctionData) constant;
-                data.initTransients(source, installer);
-                final FunctionInitializer initializer = initializers.get(data.getFunctionNodeId());
-                if (initializer != null) {
-                    initializer.setCode(installedClasses.get(initializer.getClassName()));
-                    data.initializeCode(initializer);
-                }
-            }
-        }
-
-        return mainClass;
-    }
-
-    /**
      * Cache for compiled script classes.
      */
     @SuppressWarnings("serial")
@@ -1427,7 +1459,7 @@
      * @param level            log level
      * @param mh               method handle
      * @param paramStart       first parameter to print
-     * @param printReturnValue should we print the return vaulue?
+     * @param printReturnValue should we print the return value?
      * @param text             debug printout to add
      *
      * @return instrumented method handle, or null if logger not enabled
diff --git a/src/jdk/nashorn/internal/runtime/Debug.java b/src/jdk/nashorn/internal/runtime/Debug.java
index a2d136f..7010319 100644
--- a/src/jdk/nashorn/internal/runtime/Debug.java
+++ b/src/jdk/nashorn/internal/runtime/Debug.java
@@ -26,6 +26,8 @@
 package jdk.nashorn.internal.runtime;
 
 import static jdk.nashorn.internal.parser.TokenType.EOF;
+
+import jdk.nashorn.api.scripting.NashornException;
 import jdk.nashorn.internal.parser.Lexer;
 import jdk.nashorn.internal.parser.Token;
 import jdk.nashorn.internal.parser.TokenStream;
@@ -63,6 +65,15 @@
     }
 
     /**
+     * Return a formatted script stack trace string with frames information separated by '\n'.
+     * This is a shortcut for {@code NashornException.getScriptStackString(new Throwable())}.
+     * @return formatted stack trace string
+     */
+    public static String scriptStack() {
+        return NashornException.getScriptStackString(new Throwable());
+    }
+
+    /**
      * Return the system identity hashcode for an object as a human readable
      * string
      *
diff --git a/src/jdk/nashorn/internal/runtime/DebuggerSupport.java b/src/jdk/nashorn/internal/runtime/DebuggerSupport.java
index d5dc560..030d1c8 100644
--- a/src/jdk/nashorn/internal/runtime/DebuggerSupport.java
+++ b/src/jdk/nashorn/internal/runtime/DebuggerSupport.java
@@ -3,18 +3,18 @@
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General  License version 2 only, as
+ * 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  License
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
  *
- * You should have received a copy of the GNU General  License version
+ * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  *
@@ -156,7 +156,7 @@
         final Context context = global.getContext();
 
         try {
-            return context.eval(initialScope, string, callThis, ScriptRuntime.UNDEFINED, false);
+            return context.eval(initialScope, string, callThis, ScriptRuntime.UNDEFINED);
         } catch (final Throwable ex) {
             return returnException ? ex : null;
         }
diff --git a/src/jdk/nashorn/internal/runtime/ErrorManager.java b/src/jdk/nashorn/internal/runtime/ErrorManager.java
index 9a20381..4d4c8b1 100644
--- a/src/jdk/nashorn/internal/runtime/ErrorManager.java
+++ b/src/jdk/nashorn/internal/runtime/ErrorManager.java
@@ -113,7 +113,7 @@
 
         // Pointer to column.
         for (int i = 0; i < column; i++) {
-            if (sourceLine.charAt(i) == '\t') {
+            if (i < sourceLine.length() && sourceLine.charAt(i) == '\t') {
                 sb.append('\t');
             } else {
                 sb.append(' ');
diff --git a/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java b/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java
index c868aab..2540277 100644
--- a/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java
+++ b/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java
@@ -27,6 +27,7 @@
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodType;
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -72,11 +73,6 @@
     }
 
     @Override
-    boolean isRecompilable() {
-        return false;
-    }
-
-    @Override
     protected boolean needsCallee() {
         final boolean needsCallee = code.getFirst().needsCallee();
         assert allNeedCallee(needsCallee);
@@ -93,6 +89,25 @@
     }
 
     @Override
+    CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden, boolean linkLogicOkay) {
+        assert isValidCallSite(callSiteType) : callSiteType;
+
+        CompiledFunction best = null;
+        for (final CompiledFunction candidate: code) {
+            if (!linkLogicOkay && candidate.hasLinkLogic()) {
+                // Skip! Version with no link logic is desired, but this one has link logic!
+                continue;
+            }
+
+            if (!forbidden.contains(candidate) && candidate.betterThanFinal(best, callSiteType)) {
+                best = candidate;
+            }
+        }
+
+        return best;
+    }
+
+    @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
diff --git a/src/jdk/nashorn/internal/runtime/FindProperty.java b/src/jdk/nashorn/internal/runtime/FindProperty.java
index 3b153c5..98ddf24 100644
--- a/src/jdk/nashorn/internal/runtime/FindProperty.java
+++ b/src/jdk/nashorn/internal/runtime/FindProperty.java
@@ -297,4 +297,3 @@
     }
 
 }
-
diff --git a/src/jdk/nashorn/internal/runtime/FunctionInitializer.java b/src/jdk/nashorn/internal/runtime/FunctionInitializer.java
index 906024d..a2139cc 100644
--- a/src/jdk/nashorn/internal/runtime/FunctionInitializer.java
+++ b/src/jdk/nashorn/internal/runtime/FunctionInitializer.java
@@ -60,17 +60,6 @@
     }
 
     /**
-     * Copy constructor.
-     *
-     * @param init original initializer
-     */
-    FunctionInitializer(final FunctionInitializer init) {
-        this.className = init.getClassName();
-        this.methodType = init.getMethodType();
-        this.flags = init.getFlags();
-    }
-
-    /**
      * Constructor.
      *
      * @param functionNode the function node
@@ -130,7 +119,7 @@
      * Set the class implementing the function
      * @param code the class
      */
-    public void setCode(final Class<?> code) {
+    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");
diff --git a/src/jdk/nashorn/internal/runtime/FunctionScope.java b/src/jdk/nashorn/internal/runtime/FunctionScope.java
index 133c64f..30d06ff 100644
--- a/src/jdk/nashorn/internal/runtime/FunctionScope.java
+++ b/src/jdk/nashorn/internal/runtime/FunctionScope.java
@@ -35,17 +35,12 @@
  *
  * The constructor of this class is responsible for any function prologue
  * involving the scope.
- *
- * TODO see NASHORN-715.
  */
-public class FunctionScope extends ScriptObject implements Scope {
+public class FunctionScope extends Scope {
 
     /** Area to store scope arguments. (public for access from scripts.) */
     public final ScriptObject arguments;
 
-    /** Flag to indicate that a split method issued a return statement */
-    private int splitState = -1;
-
     /**
      * Constructor
      *
@@ -56,7 +51,6 @@
     public FunctionScope(final PropertyMap map, final ScriptObject callerScope, final ScriptObject arguments) {
         super(callerScope, map);
         this.arguments = arguments;
-        setIsScope();
     }
 
     /**
@@ -68,7 +62,6 @@
     public FunctionScope(final PropertyMap map, final ScriptObject callerScope) {
         super(callerScope, map);
         this.arguments = null;
-        setIsScope();
     }
 
     /**
@@ -82,23 +75,4 @@
         super(map, primitiveSpill, objectSpill);
         this.arguments = null;
     }
-
-
-    /**
-     * Get the current split state.
-     * @return current split state
-     */
-    @Override
-    public int getSplitState() {
-        return splitState;
-    }
-
-    /**
-     * Set the current split state.
-     * @param state current split state
-     */
-    @Override
-    public void setSplitState(final int state) {
-        splitState = state;
-    }
 }
diff --git a/src/jdk/nashorn/internal/runtime/GlobalConstants.java b/src/jdk/nashorn/internal/runtime/GlobalConstants.java
index cd1061c..7f93e70 100644
--- a/src/jdk/nashorn/internal/runtime/GlobalConstants.java
+++ b/src/jdk/nashorn/internal/runtime/GlobalConstants.java
@@ -67,7 +67,7 @@
  *
  * 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.
+ * just end up relinking our way into megamorphism.
  *
  * Also it has to be noted that this kind of linking creates a coupling between a Global
  * and the call sites in compiled code belonging to the Context. For this reason, the
diff --git a/src/jdk/nashorn/internal/runtime/GlobalFunctions.java b/src/jdk/nashorn/internal/runtime/GlobalFunctions.java
index c7094ad..eec1fae 100644
--- a/src/jdk/nashorn/internal/runtime/GlobalFunctions.java
+++ b/src/jdk/nashorn/internal/runtime/GlobalFunctions.java
@@ -187,14 +187,14 @@
 
         double result = 0.0;
         int digit;
-        // we should see atleast one valid digit
+        // we should see at least one valid digit
         boolean entered = false;
         while (idx < length) {
             digit = fastDigit(str.charAt(idx++), radix);
             if (digit < 0) {
                 break;
             }
-            // we have seen atleast one valid digit in the specified radix
+            // we have seen at least one valid digit in the specified radix
             entered = true;
             result *= radix;
             result += digit;
diff --git a/src/jdk/nashorn/internal/runtime/JSONFunctions.java b/src/jdk/nashorn/internal/runtime/JSONFunctions.java
index a400bbd..d265e6d 100644
--- a/src/jdk/nashorn/internal/runtime/JSONFunctions.java
+++ b/src/jdk/nashorn/internal/runtime/JSONFunctions.java
@@ -25,19 +25,10 @@
 
 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;
-import jdk.nashorn.internal.ir.LiteralNode;
-import jdk.nashorn.internal.ir.Node;
-import jdk.nashorn.internal.ir.ObjectNode;
-import jdk.nashorn.internal.ir.PropertyNode;
-import jdk.nashorn.internal.ir.UnaryNode;
 import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.parser.JSONParser;
-import jdk.nashorn.internal.parser.TokenType;
 import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
 
@@ -78,20 +69,19 @@
      * @return Object representation of JSON text given
      */
     public static Object parse(final Object text, final Object reviver) {
-        final String     str     = JSType.toString(text);
-        final JSONParser parser  = new JSONParser(sourceFor("<json>", str), new Context.ThrowErrorManager());
-
-        Node node;
+        final String     str    = JSType.toString(text);
+        final Global     global = Context.getGlobal();
+        final boolean    dualFields = ((ScriptObject) global).useDualFields();
+        final JSONParser parser = new JSONParser(str, global, dualFields);
+        final Object     value;
 
         try {
-            node = parser.parse();
+            value = parser.parse();
         } catch (final ParserException e) {
             throw ECMAErrors.syntaxError(e, "invalid.json", e.getMessage());
         }
 
-        final Global global = Context.getGlobal();
-        final Object unfiltered = convertNode(global, node);
-        return applyReviver(global, unfiltered, reviver);
+        return applyReviver(global, value, reviver);
     }
 
     // -- Internals only below this point
@@ -113,16 +103,28 @@
         final Object val = holder.get(name);
         if (val instanceof ScriptObject) {
             final ScriptObject     valueObj = (ScriptObject)val;
-            final Iterator<String> iter     = valueObj.propertyIterator();
+            if (valueObj.isArray()) {
+                final int length = JSType.toInteger(valueObj.getLength());
+                for (int i = 0; i < length; i++) {
+                    final String key = Integer.toString(i);
+                    final Object newElement = walk(valueObj, key, reviver);
 
-            while (iter.hasNext()) {
-                final String key        = iter.next();
-                final Object newElement = walk(valueObj, key, reviver);
+                    if (newElement == ScriptRuntime.UNDEFINED) {
+                        valueObj.delete(i, false);
+                    } else {
+                        setPropertyValue(valueObj, key, newElement);
+                    }
+                }
+            } else {
+                final String[] keys = valueObj.getOwnKeys(false);
+                for (final String key : keys) {
+                    final Object newElement = walk(valueObj, key, reviver);
 
-                if (newElement == ScriptRuntime.UNDEFINED) {
-                    valueObj.delete(key, false);
-                } else {
-                    setPropertyValue(valueObj, key, newElement);
+                    if (newElement == ScriptRuntime.UNDEFINED) {
+                        valueObj.delete(key, false);
+                    } else {
+                        setPropertyValue(valueObj, key, newElement);
+                    }
                 }
             }
         }
@@ -137,61 +139,6 @@
         }
     }
 
-    // Converts IR node to runtime value
-    private static Object convertNode(final Global global, final Node node) {
-        if (node instanceof LiteralNode) {
-            // check for array literal
-            if (node.tokenType() == TokenType.ARRAY) {
-                assert node instanceof LiteralNode.ArrayLiteralNode;
-                final Node[] elements = ((LiteralNode.ArrayLiteralNode)node).getValue();
-
-                // NOTE: We cannot use LiteralNode.isNumericArray() here as that
-                // method uses symbols of element nodes. Since we don't do lower
-                // pass, there won't be any symbols!
-                if (isNumericArray(elements)) {
-                    final double[] values = new double[elements.length];
-                    int   index = 0;
-
-                    for (final Node elem : elements) {
-                        values[index++] = JSType.toNumber(convertNode(global, elem));
-                    }
-                    return global.wrapAsObject(values);
-                }
-
-                final Object[] values = new Object[elements.length];
-                int   index = 0;
-
-                for (final Node elem : elements) {
-                    values[index++] = convertNode(global, elem);
-                }
-
-                return global.wrapAsObject(values);
-            }
-
-            return ((LiteralNode<?>)node).getValue();
-
-        } else if (node instanceof ObjectNode) {
-            final ObjectNode   objNode  = (ObjectNode) node;
-            final ScriptObject object   = global.newObject();
-
-            for (final PropertyNode pNode: objNode.getElements()) {
-                final Node         valueNode = pNode.getValue();
-
-                final String name = pNode.getKeyName();
-                final Object value = convertNode(global, valueNode);
-                setPropertyValue(object, name, value);
-            }
-
-            return object;
-        } else if (node instanceof UnaryNode) {
-            // UnaryNode used only to represent negative number JSON value
-            final UnaryNode unaryNode = (UnaryNode)node;
-            return -((LiteralNode<?>)unaryNode.getExpression()).getNumber();
-        } else {
-            return null;
-        }
-    }
-
     // add a new property if does not exist already, or else set old property
     private static void setPropertyValue(final ScriptObject sobj, final String name, final Object value) {
         final int index = ArrayIndex.getArrayIndex(name);
@@ -207,14 +154,4 @@
         }
     }
 
-    // does the given IR node represent a numeric array?
-    private static boolean isNumericArray(final Node[] values) {
-        for (final Node node : values) {
-            if (node instanceof LiteralNode && ((LiteralNode<?>)node).getValue() instanceof Number) {
-                continue;
-            }
-            return false;
-        }
-        return true;
-    }
 }
diff --git a/src/jdk/nashorn/internal/runtime/JSONListAdapter.java b/src/jdk/nashorn/internal/runtime/JSONListAdapter.java
new file mode 100644
index 0000000..7ce63fb
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/JSONListAdapter.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.util.Collection;
+import java.util.List;
+import java.util.Set;
+import jdk.nashorn.api.scripting.AbstractJSObject;
+import jdk.nashorn.api.scripting.JSObject;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
+import jdk.nashorn.internal.objects.Global;
+
+/**
+ * A {@link ListAdapter} that also implements {@link JSObject}. Named {@code JSONListAdapter} as it is used as a
+ * {@code JSObject} implementing the {@link List} interface, which is the expected interface to be implemented by
+ * JSON-parsed arrays when they are handled in Java. We aren't implementing {@link JSObject} on {@link ListAdapter}
+ * directly since that'd have implications for other uses of list adapter (e.g. interferences of JSObject default
+ * value calculation vs. List's {@code toString()} etc.)
+ */
+public final class JSONListAdapter extends ListAdapter implements JSObject {
+    /**
+     * Creates a new JSON list adapter.
+     * @param obj the underlying object being exposed as a list.
+     * @param global the home global of the underlying object.
+     */
+    public JSONListAdapter(final JSObject obj, final Global global) {
+        super(obj, global);
+    }
+
+    /**
+     * Unwraps this adapter into its underlying non-JSObject representative.
+     * @param homeGlobal the home global for unwrapping
+     * @return either the unwrapped object or this if it should not be unwrapped in the specified global.
+     */
+    public Object unwrap(final Object homeGlobal) {
+        final Object unwrapped = ScriptObjectMirror.unwrap(obj, homeGlobal);
+        return unwrapped != obj ? unwrapped : this;
+    }
+
+    @Override
+    public Object call(final Object thiz, final Object... args) {
+        return obj.call(thiz, args);
+    }
+
+    @Override
+    public Object newObject(final Object... args) {
+        return obj.newObject(args);
+    }
+
+    @Override
+    public Object eval(final String s) {
+        return obj.eval(s);
+    }
+
+    @Override
+    public Object getMember(final String name) {
+        return obj.getMember(name);
+    }
+
+    @Override
+    public Object getSlot(final int index) {
+        return obj.getSlot(index);
+    }
+
+    @Override
+    public boolean hasMember(final String name) {
+        return obj.hasMember(name);
+    }
+
+    @Override
+    public boolean hasSlot(final int slot) {
+        return obj.hasSlot(slot);
+    }
+
+    @Override
+    public void removeMember(final String name) {
+        obj.removeMember(name);
+    }
+
+    @Override
+    public void setMember(final String name, final Object value) {
+        obj.setMember(name, value);
+    }
+
+    @Override
+    public void setSlot(final int index, final Object value) {
+        obj.setSlot(index, value);
+    }
+
+    @Override
+    public Set<String> keySet() {
+        return obj.keySet();
+    }
+
+    @Override
+    public Collection<Object> values() {
+        return obj.values();
+    }
+
+    @Override
+    public boolean isInstance(final Object instance) {
+        return obj.isInstance(instance);
+    }
+
+    @Override
+    public boolean isInstanceOf(final Object clazz) {
+        return obj.isInstanceOf(clazz);
+    }
+
+    @Override
+    public String getClassName() {
+        return obj.getClassName();
+    }
+
+    @Override
+    public boolean isFunction() {
+        return obj.isFunction();
+    }
+
+    @Override
+    public boolean isStrictFunction() {
+        return obj.isStrictFunction();
+    }
+
+    @Override
+    public boolean isArray() {
+        return obj.isArray();
+    }
+
+    @Override @Deprecated
+    public double toNumber() {
+        return obj.toNumber();
+    }
+
+    /**
+     * Implements this object's {@code [[DefaultValue]]} method by returning its wrapped object's {@code [[DefaultValue]]}.
+     *
+     * @param hint the type hint. Should be either {@code null}, {@code Number.class} or {@code String.class}.
+     * @return the wrapped object's default value.
+     * @throws UnsupportedOperationException if the conversion can't be performed. The engine will convert this
+     * exception into a JavaScript {@code TypeError}.
+     */
+    public Object getDefaultValue(final Class<?> hint) {
+        return AbstractJSObject.getDefaultValue(obj, hint);
+    }
+}
diff --git a/src/jdk/nashorn/internal/runtime/JSObjectListAdapter.java b/src/jdk/nashorn/internal/runtime/JSObjectListAdapter.java
deleted file mode 100644
index e1357d6..0000000
--- a/src/jdk/nashorn/internal/runtime/JSObjectListAdapter.java
+++ /dev/null
@@ -1,56 +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 jdk.nashorn.api.scripting.JSObject;
-
-/**
- * A ListAdapter that can wraps a JSObject.
- */
-public final class JSObjectListAdapter extends ListAdapter {
-    /**
-     * Creates a new list wrapper for the specified JSObject.
-     * @param obj JSOcript the object to wrap
-     */
-    public JSObjectListAdapter(final JSObject obj) {
-        super(obj);
-    }
-
-    @Override
-    public int size() {
-        return JSType.toInt32(((JSObject)obj).getMember("length"));
-    }
-
-    @Override
-    protected Object getAt(final int index) {
-        return ((JSObject)obj).getSlot(index);
-    }
-
-    @Override
-    protected void setAt(final int index, final Object element) {
-        ((JSObject)obj).setSlot(index, element);
-    }
-}
diff --git a/src/jdk/nashorn/internal/runtime/JSType.java b/src/jdk/nashorn/internal/runtime/JSType.java
index 7e54b1e..0c81eeb 100644
--- a/src/jdk/nashorn/internal/runtime/JSType.java
+++ b/src/jdk/nashorn/internal/runtime/JSType.java
@@ -26,17 +26,17 @@
 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.AbstractJSObject;
 import jdk.nashorn.api.scripting.JSObject;
 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
 import jdk.nashorn.internal.codegen.types.Type;
@@ -180,10 +180,10 @@
     /** 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);
 
-    /** Div zero wrapper for long division that handles (0/0) >>> 0 == 0 */
+    /** Div zero wrapper for long division that handles (0/0) &gt;&gt;&gt; 0 == 0 */
     public static final Call DIV_ZERO_LONG        = staticCall(JSTYPE_LOOKUP, JSType.class, "divZero", long.class, long.class, long.class);
 
-    /** Mod zero wrapper for long division that handles (0%0) >>> 0 == 0 */
+    /** Mod zero wrapper for long division that handles (0%0) &gt;&gt;&gt; 0 == 0 */
     public static final Call REM_ZERO_LONG       = staticCall(JSTYPE_LOOKUP, JSType.class, "remZero", long.class, long.class, long.class);
 
     /** Mod exact wrapper for potentially integer remainders that turns into float point */
@@ -201,16 +201,9 @@
     /** Method handle to convert a JS Object to a Java array. */
     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(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(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
@@ -311,7 +304,7 @@
             return JSType.BOOLEAN;
         }
 
-        if (obj instanceof String || obj instanceof ConsString) {
+        if (isString(obj)) {
             return JSType.STRING;
         }
 
@@ -349,7 +342,7 @@
             return JSType.BOOLEAN;
         }
 
-        if (obj instanceof String || obj instanceof ConsString) {
+        if (isString(obj)) {
             return JSType.STRING;
         }
 
@@ -384,8 +377,8 @@
     }
 
     /**
-     * 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)}.
+     * 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, use {@link #isStrictlyRepresentableAsInt(double)}.
      *
      * @param number a double to inspect
      *
@@ -396,6 +389,18 @@
     }
 
     /**
+     * Returns true if double number can be represented as an int. Note that it returns false for negative
+     * zero. If you don't need to distinguish negative zero, use {@link #isRepresentableAsInt(double)}.
+     *
+     * @param number a double to inspect
+     *
+     * @return true for int representable doubles
+     */
+    public static boolean isStrictlyRepresentableAsInt(final double number) {
+        return isRepresentableAsInt(number) && isNotNegativeZero(number);
+    }
+
+    /**
      * Returns true if Object can be represented as an int
      *
      * @param obj an object to inspect
@@ -410,8 +415,8 @@
     }
 
     /**
-     * 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)}.
+     * 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, use {@link #isStrictlyRepresentableAsLong(double)}.
      *
      * @param number a double to inspect
      * @return true for long representable doubles
@@ -421,6 +426,18 @@
     }
 
     /**
+     * Returns true if double number can be represented as a long. Note that it returns false for negative
+     * zero. If you don't need to distinguish negative zero, use {@link #isRepresentableAsLong(double)}.
+     *
+     * @param number a double to inspect
+     *
+     * @return true for long representable doubles
+     */
+    public static boolean isStrictlyRepresentableAsLong(final double number) {
+        return isRepresentableAsLong(number) && isNotNegativeZero(number);
+    }
+
+    /**
      * Returns true if Object can be represented as a long
      *
      * @param obj an object to inspect
@@ -435,12 +452,12 @@
     }
 
     /**
-     * Returns true if the number is the negative zero ({@code -0.0d}).
+     * Returns true if the number is not the negative zero ({@code -0.0d}).
      * @param number the number to test
-     * @return true if it is the negative zero, false otherwise.
+     * @return true if it is not the negative zero, false otherwise.
      */
-    public static boolean isNegativeZero(final double number) {
-        return number == 0.0d && Double.doubleToRawLongBits(number) == 0x8000000000000000L;
+    private static boolean isNotNegativeZero(final double number) {
+        return Double.doubleToRawLongBits(number) != 0x8000000000000000L;
     }
 
     /**
@@ -455,8 +472,7 @@
                obj == ScriptRuntime.UNDEFINED ||
                obj instanceof Boolean ||
                obj instanceof Number ||
-               obj instanceof String ||
-               obj instanceof ConsString;
+               isString(obj);
     }
 
    /**
@@ -480,20 +496,50 @@
      * @return the primitive form of the object
      */
     public static Object toPrimitive(final Object obj, final Class<?> hint) {
-        return obj instanceof ScriptObject ? toPrimitive((ScriptObject)obj, hint) : obj;
+        if (obj instanceof ScriptObject) {
+            return toPrimitive((ScriptObject)obj, hint);
+        } else if (isPrimitive(obj)) {
+            return obj;
+        } else if (obj instanceof JSObject) {
+            return toPrimitive((JSObject)obj, hint);
+        } else if (obj instanceof StaticClass) {
+            final String name = ((StaticClass)obj).getRepresentedClass().getName();
+            return new StringBuilder(12 + name.length()).append("[JavaClass ").append(name).append(']').toString();
+        }
+        return obj.toString();
     }
 
     private static Object toPrimitive(final ScriptObject sobj, final Class<?> hint) {
-        final Object result = sobj.getDefaultValue(hint);
+        return requirePrimitive(sobj.getDefaultValue(hint));
+    }
 
+    private static Object requirePrimitive(final Object result) {
         if (!isPrimitive(result)) {
             throw typeError("bad.default.value", result.toString());
         }
-
         return result;
     }
 
     /**
+     * Primitive converter for a {@link JSObject} including type hint. Invokes
+     * {@link AbstractJSObject#getDefaultValue(JSObject, Class)} and translates any thrown
+     * {@link UnsupportedOperationException} to an ECMAScript {@code TypeError}.
+     * See ECMA 9.1 ToPrimitive
+     *
+     * @param jsobj  a JSObject
+     * @param hint a type hint
+     *
+     * @return the primitive form of the JSObject
+     */
+    public static Object toPrimitive(final JSObject jsobj, final Class<?> hint) {
+        try {
+            return requirePrimitive(AbstractJSObject.getDefaultValue(jsobj, hint));
+        } catch (final UnsupportedOperationException e) {
+            throw new ECMAException(Context.getGlobal().newTypeError(e.getMessage()), e);
+        }
+    }
+
+    /**
      * Combines a hintless toPrimitive and a toString call.
      *
      * @param obj  an object
@@ -547,7 +593,7 @@
             return num != 0 && !Double.isNaN(num);
         }
 
-        if (obj instanceof String || obj instanceof ConsString) {
+        if (isString(obj)) {
             return ((CharSequence)obj).length() > 0;
         }
 
@@ -598,6 +644,15 @@
     }
 
     /**
+     * Returns true if object represents a primitive JavaScript string value.
+     * @param obj the object
+     * @return true if the object represents a primitive JavaScript string value.
+     */
+    public static boolean isString(final Object obj) {
+        return obj instanceof String || obj instanceof ConsString;
+    }
+
+    /**
      * JavaScript compliant conversion of integer to String
      *
      * @param num an integer
@@ -723,6 +778,48 @@
         return toNumberGeneric(obj);
     }
 
+    /**
+     * Converts an object for a comparison with a number. Almost identical to {@link #toNumber(Object)} but
+     * converts {@code null} to {@code NaN} instead of zero, so it won't compare equal to zero.
+     *
+     * @param obj  an object
+     *
+     * @return a number
+     */
+    public static double toNumberForEq(final Object obj) {
+        return obj == null ? Double.NaN : toNumber(obj);
+    }
+
+    /**
+     * Converts an object for strict comparison with a number. Returns {@code NaN} for any object that is not
+     * a {@link Number}, so only boxed numerics can compare strictly equal to numbers.
+     *
+     * @param obj  an object
+     *
+     * @return a number
+     */
+    public static double toNumberForStrictEq(final Object obj) {
+        if (obj instanceof Double) {
+            return (Double)obj;
+        }
+        if (obj instanceof Number) {
+            return ((Number)obj).doubleValue();
+        }
+        return Double.NaN;
+    }
+
+
+    /**
+     * JavaScript compliant conversion of Boolean to number
+     * See ECMA 9.3 ToNumber
+     *
+     * @param b a boolean
+     *
+     * @return JS numeric value of the boolean: 1.0 or 0.0
+     */
+    public static double toNumber(final Boolean b) {
+        return b ? 1d : +0d;
+    }
 
     /**
      * JavaScript compliant conversion of Object to number
@@ -853,11 +950,15 @@
         if (start + 1 < end && f == '0' && Character.toLowerCase(str.charAt(start + 1)) == 'x') {
             //decode hex string
             value = parseRadix(str.toCharArray(), start + 2, end, 16);
+        } else if (f == 'I' && end - start == 8 && str.regionMatches(start, "Infinity", 0, 8)) {
+            return negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
         } else {
-            // Fast (no NumberFormatException) path to NaN for non-numeric strings. We allow those starting with "I" or
-            // "N" to allow for parsing "NaN" and "Infinity" correctly.
-            if ((f < '0' || f > '9') && f != '.' && f != 'I' && f != 'N') {
-                return Double.NaN;
+            // Fast (no NumberFormatException) path to NaN for non-numeric strings.
+            for (int i = start; i < end; i++) {
+                f = str.charAt(i);
+                if ((f < '0' || f > '9') && f != '.' && f != 'e' && f != 'E' && f != '+' && f != '-') {
+                    return Double.NaN;
+                }
             }
             try {
                 value = Double.parseDouble(str.substring(start, end));
@@ -1268,24 +1369,6 @@
     }
 
     /**
-     * Converts a JavaScript object to a Java List. See {@link ListAdapter} for details.
-     * @param obj the object to convert. Can be any array-like object.
-     * @return a List that is live-backed by the JavaScript object.
-     */
-    public static List<?> toJavaList(final Object obj) {
-        return ListAdapter.create(obj);
-    }
-
-    /**
-     * Converts a JavaScript object to a Java Deque. See {@link ListAdapter} for details.
-     * @param obj the object to convert. Can be any array-like object.
-     * @return a Deque that is live-backed by the JavaScript object.
-     */
-    public static Deque<?> toJavaDeque(final Object obj) {
-        return ListAdapter.create(obj);
-    }
-
-    /**
      * Check if an object is null or undefined
      *
      * @param obj object to check
@@ -1301,6 +1384,10 @@
             return (String)obj;
         }
 
+        if (obj instanceof ConsString) {
+            return obj.toString();
+        }
+
         if (obj instanceof Number) {
             return toString(((Number)obj).doubleValue());
         }
@@ -1313,23 +1400,19 @@
             return "null";
         }
 
-        if (obj instanceof ScriptObject) {
-            if (safe) {
-                final ScriptObject sobj = (ScriptObject)obj;
-                final Global gobj = Context.getGlobal();
-                return gobj.isError(sobj) ?
-                    ECMAException.safeToString(sobj) :
-                    sobj.safeToString();
-            }
-
-            return toString(toPrimitive(obj, String.class));
+        if (obj instanceof Boolean) {
+            return obj.toString();
         }
 
-        if (obj instanceof StaticClass) {
-            return "[JavaClass " + ((StaticClass)obj).getRepresentedClass().getName() + "]";
+        if (safe && obj instanceof ScriptObject) {
+            final ScriptObject sobj = (ScriptObject)obj;
+            final Global gobj = Context.getGlobal();
+            return gobj.isError(sobj) ?
+                ECMAException.safeToString(sobj) :
+                sobj.safeToString();
         }
 
-        return obj.toString();
+        return toString(toPrimitive(obj, String.class));
     }
 
     // trim from left for JS whitespaces.
@@ -1822,18 +1905,18 @@
         }
 
         if (obj instanceof Boolean) {
-            return (Boolean)obj ? 1 : +0.0;
+            return toNumber((Boolean)obj);
         }
 
         if (obj instanceof ScriptObject) {
             return toNumber((ScriptObject)obj);
         }
 
-        if (obj instanceof JSObject) {
-            return ((JSObject)obj).toNumber();
+        if (obj instanceof Undefined) {
+            return Double.NaN;
         }
 
-        return Double.NaN;
+        return toNumber(toPrimitive(obj, Number.class));
     }
 
     private static Object invoke(final MethodHandle mh, final Object arg) {
@@ -1885,13 +1968,9 @@
     /**
      * Get the unboxed (primitive) type for an object
      * @param o object
-     * @return primive type or Object.class if not primitive
+     * @return primitive 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) {
diff --git a/src/jdk/nashorn/internal/runtime/ListAdapter.java b/src/jdk/nashorn/internal/runtime/ListAdapter.java
index 25179a5..4d0e169 100644
--- a/src/jdk/nashorn/internal/runtime/ListAdapter.java
+++ b/src/jdk/nashorn/internal/runtime/ListAdapter.java
@@ -25,17 +25,19 @@
 
 package jdk.nashorn.internal.runtime;
 
+import java.lang.invoke.MethodHandle;
 import java.util.AbstractList;
 import java.util.Deque;
 import java.util.Iterator;
 import java.util.ListIterator;
 import java.util.NoSuchElementException;
+import java.util.Objects;
 import java.util.RandomAccess;
 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;
 
 /**
  * An adapter that can wrap any ECMAScript Array-like object (that adheres to the array rules for the property
@@ -50,82 +52,43 @@
  * operations respectively, while {@link #addLast(Object)} and {@link #removeLast()} will translate to {@code push} and
  * {@code pop}.
  */
-public abstract class ListAdapter extends AbstractList<Object> implements RandomAccess, Deque<Object> {
-    // These add to the back and front of the list
-    private static final Object PUSH    = new Object();
-    private static InvokeByName getPUSH() {
-        return Context.getGlobal().getInvokeByName(PUSH,
-                new Callable<InvokeByName>() {
-                    @Override
-                    public InvokeByName call() {
-                        return new InvokeByName("push", Object.class, void.class, Object.class);
-                    }
-                });
-    }
+public class ListAdapter extends AbstractList<Object> implements RandomAccess, Deque<Object> {
+    // Invoker creator for methods that add to the start or end of the list: PUSH and UNSHIFT. Takes fn, this, and value, returns void.
+    private static final Callable<MethodHandle> ADD_INVOKER_CREATOR = invokerCreator(void.class, Object.class, JSObject.class, Object.class);
 
+    // PUSH adds to the start of the list
+    private static final Object PUSH = new Object();
+    // UNSHIFT adds to the end of the list
     private static final Object UNSHIFT = new Object();
-    private static InvokeByName getUNSHIFT() {
-        return Context.getGlobal().getInvokeByName(UNSHIFT,
-                new Callable<InvokeByName>() {
-                    @Override
-                    public InvokeByName call() {
-                        return new InvokeByName("unshift", Object.class, void.class, Object.class);
-                    }
-                });
-    }
 
-    // These remove from the back and front of the list
+    // Invoker creator for methods that remove from the tail or head of the list: POP and SHIFT. Takes fn, this, returns Object.
+    private static final Callable<MethodHandle> REMOVE_INVOKER_CREATOR = invokerCreator(Object.class, Object.class, JSObject.class);
+
+    // POP removes from the start of the list
     private static final Object POP = new Object();
-    private static InvokeByName getPOP() {
-        return Context.getGlobal().getInvokeByName(POP,
-                new Callable<InvokeByName>() {
-                    @Override
-                    public InvokeByName call() {
-                        return new InvokeByName("pop", Object.class, Object.class);
-                    }
-                });
-    }
-
+    // SHIFT removes from the end of the list
     private static final Object SHIFT = new Object();
-    private static InvokeByName getSHIFT() {
-        return Context.getGlobal().getInvokeByName(SHIFT,
-                new Callable<InvokeByName>() {
-                    @Override
-                    public InvokeByName call() {
-                        return new InvokeByName("shift", Object.class, Object.class);
-                    }
-                });
-    }
 
-    // These insert and remove in the middle of the list
+    // SPLICE can be used to add a value in the middle of the list.
     private static final Object SPLICE_ADD = new Object();
-    private static InvokeByName getSPLICE_ADD() {
-        return Context.getGlobal().getInvokeByName(SPLICE_ADD,
-                new Callable<InvokeByName>() {
-                    @Override
-                    public InvokeByName call() {
-                        return new InvokeByName("splice", Object.class, void.class, int.class, int.class, Object.class);
-                    }
-                });
-    }
+    private static final Callable<MethodHandle> SPLICE_ADD_INVOKER_CREATOR = invokerCreator(void.class, Object.class, JSObject.class, int.class, int.class, Object.class);
 
+    // SPLICE can also be used to remove values from the middle of the list.
     private static final Object SPLICE_REMOVE = new Object();
-    private static InvokeByName getSPLICE_REMOVE() {
-        return  Context.getGlobal().getInvokeByName(SPLICE_REMOVE,
-                new Callable<InvokeByName>() {
-                    @Override
-                    public InvokeByName call() {
-                        return new InvokeByName("splice", Object.class, void.class, int.class, int.class);
-                    }
-                });
-    }
+    private static final Callable<MethodHandle> SPLICE_REMOVE_INVOKER_CREATOR = invokerCreator(void.class, Object.class, JSObject.class, int.class, int.class);
 
     /** wrapped object */
-    protected final Object obj;
+    final JSObject obj;
+    private final Global global;
 
     // allow subclasses only in this package
-    ListAdapter(final Object obj) {
+    ListAdapter(final JSObject obj, final Global global) {
+        if (global == null) {
+            throw new IllegalStateException(ECMAErrors.getMessage("list.adapter.null.global"));
+        }
+
         this.obj = obj;
+        this.global = global;
     }
 
     /**
@@ -135,14 +98,17 @@
      * @return A ListAdapter wrapper object
      */
     public static ListAdapter create(final Object obj) {
+        final Global global = Context.getGlobal();
+        return new ListAdapter(getJSObject(obj, global), global);
+    }
+
+    private static JSObject getJSObject(final Object obj, final Global global) {
         if (obj instanceof ScriptObject) {
-            final Object mirror = ScriptObjectMirror.wrap(obj, Context.getGlobal());
-            return new JSObjectListAdapter((JSObject)mirror);
+            return (JSObject)ScriptObjectMirror.wrap(obj, global);
         } else if (obj instanceof JSObject) {
-            return new JSObjectListAdapter((JSObject)obj);
-        } else {
-            throw new IllegalArgumentException("ScriptObject or JSObject expected");
+            return (JSObject)obj;
         }
+        throw new IllegalArgumentException("ScriptObject or JSObject expected");
     }
 
     @Override
@@ -151,28 +117,18 @@
         return getAt(index);
     }
 
-    /**
-     * Get object at an index
-     * @param index index in list
-     * @return object
-     */
-    protected abstract Object getAt(final int index);
+    private Object getAt(final int index) {
+        return obj.getSlot(index);
+    }
 
     @Override
     public Object set(final int index, final Object element) {
         checkRange(index);
         final Object prevValue = getAt(index);
-        setAt(index, element);
+        obj.setSlot(index, element);
         return prevValue;
     }
 
-    /**
-     * Set object at an index
-     * @param index   index in list
-     * @param element element
-     */
-    protected abstract void setAt(final int index, final Object element);
-
     private void checkRange(final int index) {
         if(index < 0 || index >= size()) {
             throw invalidIndex(index);
@@ -180,6 +136,11 @@
     }
 
     @Override
+    public int size() {
+        return JSType.toInt32(obj.getMember("length"));
+    }
+
+    @Override
     public final void push(final Object e) {
         addFirst(e);
     }
@@ -193,10 +154,7 @@
     @Override
     public final void addFirst(final Object e) {
         try {
-            final InvokeByName unshiftInvoker = getUNSHIFT();
-            final Object fn = unshiftInvoker.getGetter().invokeExact(obj);
-            checkFunction(fn, unshiftInvoker);
-            unshiftInvoker.getInvoker().invokeExact(fn, obj, e);
+            getDynamicInvoker(UNSHIFT, ADD_INVOKER_CREATOR).invokeExact(getFunction("unshift"), obj, e);
         } catch(RuntimeException | Error ex) {
             throw ex;
         } catch(final Throwable t) {
@@ -207,10 +165,7 @@
     @Override
     public final void addLast(final Object e) {
         try {
-            final InvokeByName pushInvoker = getPUSH();
-            final Object fn = pushInvoker.getGetter().invokeExact(obj);
-            checkFunction(fn, pushInvoker);
-            pushInvoker.getInvoker().invokeExact(fn, obj, e);
+            getDynamicInvoker(PUSH, ADD_INVOKER_CREATOR).invokeExact(getFunction("push"), obj, e);
         } catch(RuntimeException | Error ex) {
             throw ex;
         } catch(final Throwable t) {
@@ -228,10 +183,7 @@
             } else {
                 final int size = size();
                 if(index < size) {
-                    final InvokeByName spliceAddInvoker = getSPLICE_ADD();
-                    final Object fn = spliceAddInvoker.getGetter().invokeExact(obj);
-                    checkFunction(fn, spliceAddInvoker);
-                    spliceAddInvoker.getInvoker().invokeExact(fn, obj, index, 0, e);
+                    getDynamicInvoker(SPLICE_ADD, SPLICE_ADD_INVOKER_CREATOR).invokeExact(obj.getMember("splice"), obj, index, 0, e);
                 } else if(index == size) {
                     addLast(e);
                 } else {
@@ -244,10 +196,12 @@
             throw new RuntimeException(t);
         }
     }
-    private static void checkFunction(final Object fn, final InvokeByName invoke) {
+    private Object getFunction(final String name) {
+        final Object fn = obj.getMember(name);
         if(!(Bootstrap.isCallable(fn))) {
-            throw new UnsupportedOperationException("The script object doesn't have a function named " + invoke.getName());
+            throw new UnsupportedOperationException("The script object doesn't have a function named " + name);
         }
+        return fn;
     }
 
     private static IndexOutOfBoundsException invalidIndex(final int index) {
@@ -321,10 +275,7 @@
 
     private Object invokeShift() {
         try {
-            final InvokeByName shiftInvoker = getSHIFT();
-            final Object fn = shiftInvoker.getGetter().invokeExact(obj);
-            checkFunction(fn, shiftInvoker);
-            return shiftInvoker.getInvoker().invokeExact(fn, obj);
+            return getDynamicInvoker(SHIFT, REMOVE_INVOKER_CREATOR).invokeExact(getFunction("shift"), obj);
         } catch(RuntimeException | Error ex) {
             throw ex;
         } catch(final Throwable t) {
@@ -334,10 +285,7 @@
 
     private Object invokePop() {
         try {
-            final InvokeByName popInvoker = getPOP();
-            final Object fn = popInvoker.getGetter().invokeExact(obj);
-            checkFunction(fn, popInvoker);
-            return popInvoker.getInvoker().invokeExact(fn, obj);
+            return getDynamicInvoker(POP, REMOVE_INVOKER_CREATOR).invokeExact(getFunction("pop"), obj);
         } catch(RuntimeException | Error ex) {
             throw ex;
         } catch(final Throwable t) {
@@ -352,10 +300,7 @@
 
     private void invokeSpliceRemove(final int fromIndex, final int count) {
         try {
-            final InvokeByName spliceRemoveInvoker = getSPLICE_REMOVE();
-            final Object fn = spliceRemoveInvoker.getGetter().invokeExact(obj);
-            checkFunction(fn, spliceRemoveInvoker);
-            spliceRemoveInvoker.getInvoker().invokeExact(fn, obj, fromIndex, count);
+            getDynamicInvoker(SPLICE_REMOVE, SPLICE_REMOVE_INVOKER_CREATOR).invokeExact(getFunction("splice"), obj, fromIndex, count);
         } catch(RuntimeException | Error ex) {
             throw ex;
         } catch(final Throwable t) {
@@ -443,12 +388,24 @@
 
     private static boolean removeOccurrence(final Object o, final Iterator<Object> it) {
         while(it.hasNext()) {
-            final Object e = it.next();
-            if(o == null ? e == null : o.equals(e)) {
+            if(Objects.equals(o, it.next())) {
                 it.remove();
                 return true;
             }
         }
         return false;
     }
+
+    private static Callable<MethodHandle> invokerCreator(final Class<?> rtype, final Class<?>... ptypes) {
+        return new Callable<MethodHandle>() {
+            @Override
+            public MethodHandle call() {
+                return Bootstrap.createDynamicInvoker("dyn:call", rtype, ptypes);
+            }
+        };
+    }
+
+    private MethodHandle getDynamicInvoker(final Object key, final Callable<MethodHandle> creator) {
+        return global.getDynamicInvoker(key, creator);
+    }
 }
diff --git a/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java b/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
index 2d110e0..5153a27 100644
--- a/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
+++ b/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
@@ -206,7 +206,7 @@
     }
 
     @Override
-    protected Object invokeNoSuchProperty(final String key, final int programPoint) {
+    protected Object invokeNoSuchProperty(final String key, final boolean isScope, final int programPoint) {
         final Object retval = createProperty(key);
         if (isValid(programPoint)) {
             throw new UnwarrantedOptimismException(retval, programPoint);
diff --git a/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java b/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java
index e93fe60..9b53863 100644
--- a/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java
+++ b/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java
@@ -184,7 +184,7 @@
 
     @SuppressWarnings("unused")
     private static int ensureInt(final double arg, final int programPoint) {
-        if (JSType.isRepresentableAsInt(arg) && !JSType.isNegativeZero(arg)) {
+        if (JSType.isStrictlyRepresentableAsInt(arg)) {
             return (int)arg;
         }
         throw new UnwarrantedOptimismException(arg, programPoint);
@@ -206,7 +206,7 @@
         // Long into the exception.
         if (isPrimitiveNumberWrapper(arg)) {
             final double d = ((Number)arg).doubleValue();
-            if (JSType.isRepresentableAsInt(d) && !JSType.isNegativeZero(d)) {
+            if (JSType.isStrictlyRepresentableAsInt(d)) {
                 return (int)d;
             }
         }
@@ -239,7 +239,7 @@
     }
 
     private static long ensureLong(final double arg, final int programPoint) {
-        if (JSType.isRepresentableAsLong(arg) && !JSType.isNegativeZero(arg)) {
+        if (JSType.isStrictlyRepresentableAsLong(arg)) {
             return (long)arg;
         }
         throw new UnwarrantedOptimismException(arg, programPoint);
diff --git a/src/jdk/nashorn/internal/runtime/ParserException.java b/src/jdk/nashorn/internal/runtime/ParserException.java
index 5137d59..696e1d7 100644
--- a/src/jdk/nashorn/internal/runtime/ParserException.java
+++ b/src/jdk/nashorn/internal/runtime/ParserException.java
@@ -38,7 +38,7 @@
     private final Source source;
     // token responsible for this exception
     private final long token;
-    // if this is traslated as ECMA error, which type should be used?
+    // if this is translated as ECMA error, which type should be used?
     private final JSErrorType errorType;
 
     /**
diff --git a/src/jdk/nashorn/internal/runtime/Property.java b/src/jdk/nashorn/internal/runtime/Property.java
index 4225c25..71372be 100644
--- a/src/jdk/nashorn/internal/runtime/Property.java
+++ b/src/jdk/nashorn/internal/runtime/Property.java
@@ -96,6 +96,9 @@
     /** Is this property an ES6 lexical binding? */
     public static final int IS_LEXICAL_BINDING      = 1 << 10;
 
+    /** Does this property support dual field representation? */
+    public static final int DUAL_FIELDS             = 1 << 11;
+
     /** Property key. */
     private final String key;
 
@@ -286,7 +289,7 @@
      * @return true if parameter
      */
     public boolean isParameter() {
-        return (flags & IS_PARAMETER) == IS_PARAMETER;
+        return (flags & IS_PARAMETER) != 0;
     }
 
     /**
@@ -294,7 +297,7 @@
      * @return true if has arguments
      */
     public boolean hasArguments() {
-        return (flags & HAS_ARGUMENTS) == HAS_ARGUMENTS;
+        return (flags & HAS_ARGUMENTS) != 0;
     }
 
     /**
@@ -316,7 +319,7 @@
      * @return true if this is a bound property
      */
     public boolean isBound() {
-        return (flags & IS_BOUND) == IS_BOUND;
+        return (flags & IS_BOUND) != 0;
     }
 
     /**
@@ -325,7 +328,7 @@
      * @return true if this is a block-scoped variable
      */
     public boolean needsDeclaration() {
-        return (flags & NEEDS_DECLARATION) == NEEDS_DECLARATION;
+        return (flags & NEEDS_DECLARATION) != 0;
     }
 
     /**
@@ -346,16 +349,6 @@
     }
 
     /**
-     * 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
      */
@@ -364,16 +357,6 @@
     }
 
     /**
-     * Get the modify flags for this property. The modify flags are the ECMA 8.6.1
-     * flags that decide if the Property is writable, configurable and/or enumerable.
-     *
-     * @return modify flags for property
-     */
-    public int getModifyFlags() {
-        return flags & MODIFY_MASK;
-    }
-
-    /**
      * Remove property flags from the property. Properties are immutable here,
      * so any property change that results in a smaller flag set results in the
      * property being cloned. Use only the return value
@@ -579,8 +562,8 @@
 
     @Override
     public int hashCode() {
-        final Class<?> type = getLocalType();
-        return Objects.hashCode(this.key) ^ flags ^ getSlot() ^ (type == null ? 0 : type.hashCode());
+        final Class<?> t = getLocalType();
+        return Objects.hashCode(this.key) ^ flags ^ getSlot() ^ (t == null ? 0 : t.hashCode());
     }
 
     @Override
@@ -605,7 +588,7 @@
                 getKey().equals(otherProperty.getKey());
     }
 
-    private static final String type(final Class<?> type) {
+    private static String type(final Class<?> type) {
         if (type == null) {
             return "undef";
         } else if (type == int.class) {
@@ -625,8 +608,8 @@
      */
     public final String toStringShort() {
         final StringBuilder sb   = new StringBuilder();
-        final Class<?>      type = getLocalType();
-        sb.append(getKey()).append(" (").append(type(type)).append(')');
+        final Class<?>      t = getLocalType();
+        sb.append(getKey()).append(" (").append(type(t)).append(')');
         return sb.toString();
     }
 
@@ -642,7 +625,7 @@
     @Override
     public String toString() {
         final StringBuilder sb   = new StringBuilder();
-        final Class<?>      type = getLocalType();
+        final Class<?>      t = getLocalType();
 
         sb.append(indent(getKey(), 20)).
             append(" id=").
@@ -652,7 +635,7 @@
             append(") ").
             append(getClass().getSimpleName()).
             append(" {").
-            append(indent(type(type), 5)).
+            append(indent(type(t), 5)).
             append('}');
 
         if (slot != -1) {
@@ -715,7 +698,7 @@
      * @return whether this property is a function declaration or not.
      */
     public boolean isFunctionDeclaration() {
-        return (flags & IS_FUNCTION_DECLARATION) == IS_FUNCTION_DECLARATION;
+        return (flags & IS_FUNCTION_DECLARATION) != 0;
     }
 
     /**
@@ -723,6 +706,14 @@
      * @return true if this property represents a lexical binding.
      */
     public boolean isLexicalBinding() {
-        return (flags & IS_LEXICAL_BINDING) == IS_LEXICAL_BINDING;
+        return (flags & IS_LEXICAL_BINDING) != 0;
+    }
+
+    /**
+     * Does this property support dual fields for both primitive and object values?
+     * @return true if supports dual fields
+     */
+    public boolean hasDualFields() {
+        return (flags & DUAL_FIELDS) != 0;
     }
 }
diff --git a/src/jdk/nashorn/internal/runtime/PropertyListeners.java b/src/jdk/nashorn/internal/runtime/PropertyListeners.java
index 03b2c93..e4ecad7 100644
--- a/src/jdk/nashorn/internal/runtime/PropertyListeners.java
+++ b/src/jdk/nashorn/internal/runtime/PropertyListeners.java
@@ -28,6 +28,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.WeakHashMap;
+import java.util.concurrent.atomic.LongAdder;
 
 /**
  * Helper class to manage property listeners and notification.
@@ -37,8 +38,15 @@
     private Map<String, WeakPropertyMapSet> listeners;
 
     // These counters are updated in debug mode
-    private static int listenersAdded;
-    private static int listenersRemoved;
+    private static LongAdder listenersAdded;
+    private static LongAdder listenersRemoved;
+
+    static {
+        if (Context.DEBUG) {
+            listenersAdded = new LongAdder();
+            listenersRemoved = new LongAdder();
+        }
+    }
 
     /**
      * Copy constructor
@@ -54,29 +62,33 @@
      * Return aggregate listeners added to all PropertyListenerManagers
      * @return the listenersAdded
      */
-    public static int getListenersAdded() {
-        return listenersAdded;
+    public static long getListenersAdded() {
+        return listenersAdded.longValue();
     }
 
     /**
      * Return aggregate listeners removed from all PropertyListenerManagers
      * @return the listenersRemoved
      */
-    public static int getListenersRemoved() {
-        return listenersRemoved;
+    public static long getListenersRemoved() {
+        return listenersRemoved.longValue();
     }
 
     /**
-     * Return listeners added to this ScriptObject.
+     * Return number of listeners added to a ScriptObject.
      * @param obj the object
      * @return the listener count
      */
     public static int getListenerCount(final ScriptObject obj) {
-        final PropertyListeners propertyListeners = obj.getMap().getListeners();
-        if (propertyListeners != null) {
-            return propertyListeners.listeners == null ? 0 : propertyListeners.listeners.size();
-        }
-        return 0;
+        return obj.getMap().getListenerCount();
+    }
+
+    /**
+     * Return the number of listeners added to this PropertyListeners instance.
+     * @return the listener count;
+     */
+    public int getListenerCount() {
+        return listeners == null ? 0 : listeners.size();
     }
 
     // Property listener management methods
@@ -122,7 +134,7 @@
      */
     synchronized final void addListener(final String key, final PropertyMap propertyMap) {
         if (Context.DEBUG) {
-            listenersAdded++;
+            listenersAdded.increment();
         }
         if (listeners == null) {
             listeners = new WeakHashMap<>();
@@ -148,9 +160,12 @@
             final WeakPropertyMapSet set = listeners.get(prop.getKey());
             if (set != null) {
                 for (final PropertyMap propertyMap : set.elements()) {
-                    propertyMap.propertyAdded(prop);
+                    propertyMap.propertyAdded(prop, false);
                 }
                 listeners.remove(prop.getKey());
+                if (Context.DEBUG) {
+                    listenersRemoved.increment();
+                }
             }
         }
     }
@@ -165,9 +180,12 @@
             final WeakPropertyMapSet set = listeners.get(prop.getKey());
             if (set != null) {
                 for (final PropertyMap propertyMap : set.elements()) {
-                    propertyMap.propertyDeleted(prop);
+                    propertyMap.propertyDeleted(prop, false);
                 }
                 listeners.remove(prop.getKey());
+                if (Context.DEBUG) {
+                    listenersRemoved.increment();
+                }
             }
         }
     }
@@ -184,9 +202,12 @@
             final WeakPropertyMapSet set = listeners.get(oldProp.getKey());
             if (set != null) {
                 for (final PropertyMap propertyMap : set.elements()) {
-                    propertyMap.propertyModified(oldProp, newProp);
+                    propertyMap.propertyModified(oldProp, newProp, false);
                 }
                 listeners.remove(oldProp.getKey());
+                if (Context.DEBUG) {
+                    listenersRemoved.increment();
+                }
             }
         }
     }
@@ -198,7 +219,7 @@
         if (listeners != null) {
             for (final WeakPropertyMapSet set : listeners.values()) {
                 for (final PropertyMap propertyMap : set.elements()) {
-                    propertyMap.protoChanged();
+                    propertyMap.protoChanged(false);
                 }
             }
             listeners.clear();
diff --git a/src/jdk/nashorn/internal/runtime/PropertyMap.java b/src/jdk/nashorn/internal/runtime/PropertyMap.java
index 30a1513..cb791b0 100644
--- a/src/jdk/nashorn/internal/runtime/PropertyMap.java
+++ b/src/jdk/nashorn/internal/runtime/PropertyMap.java
@@ -34,7 +34,9 @@
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
 import java.lang.invoke.SwitchPoint;
+import java.lang.ref.Reference;
 import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
 import java.util.Arrays;
 import java.util.BitSet;
 import java.util.Collection;
@@ -42,6 +44,8 @@
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 import java.util.WeakHashMap;
+import java.util.concurrent.atomic.LongAdder;
+import jdk.nashorn.internal.runtime.options.Options;
 import jdk.nashorn.internal.scripts.JO;
 
 /**
@@ -53,35 +57,49 @@
  * All property maps are immutable. If a property is added, modified or removed, the mutator
  * will return a new map.
  */
-public final class PropertyMap implements Iterable<Object>, Serializable {
+public class PropertyMap implements Iterable<Object>, Serializable {
+    private static final int INITIAL_SOFT_REFERENCE_DERIVATION_LIMIT =
+            Math.max(0, Options.getIntProperty("nashorn.propertyMap.softReferenceDerivationLimit", 32));
+
     /** Used for non extensible PropertyMaps, negative logic as the normal case is extensible. See {@link ScriptObject#preventExtensions()} */
-    public static final int NOT_EXTENSIBLE        = 0b0000_0001;
+    private static final int NOT_EXTENSIBLE         = 0b0000_0001;
     /** Does this map contain valid array keys? */
-    public static final int CONTAINS_ARRAY_KEYS   = 0b0000_0010;
+    private static final int CONTAINS_ARRAY_KEYS    = 0b0000_0010;
 
     /** Map status flags. */
-    private int flags;
+    private final int flags;
 
     /** Map of properties. */
     private transient PropertyHashMap properties;
 
     /** Number of fields in use. */
-    private int fieldCount;
+    private final int fieldCount;
 
     /** Number of fields available. */
     private final int fieldMaximum;
 
     /** Length of spill in use. */
-    private int spillLength;
+    private final int spillLength;
 
     /** Structure class name */
-    private String className;
+    private final String className;
+
+    /**
+     * Countdown of number of times this property map has been derived from another property map. When it
+     * reaches zero, the property map will start using weak references instead of soft references to hold on
+     * to its history elements.
+     */
+    private final int softReferenceDerivationLimit;
+
+    /** A reference to the expected shared prototype property map. If this is set this
+     * property map should only be used if it the same as the actual prototype map. */
+    private transient SharedPropertyMap sharedProtoMap;
 
     /** {@link SwitchPoint}s for gets on inherited properties. */
-    private transient HashMap<String, SwitchPoint> protoGetSwitches;
+    private transient HashMap<String, SwitchPoint> protoSwitches;
 
     /** History of maps, used to limit map duplication. */
-    private transient WeakHashMap<Property, SoftReference<PropertyMap>> history;
+    private transient WeakHashMap<Property, Reference<PropertyMap>> history;
 
     /** History of prototypes, used to limit map duplication. */
     private transient WeakHashMap<ScriptObject, SoftReference<PropertyMap>> protoHistory;
@@ -94,59 +112,60 @@
     private static final long serialVersionUID = -7041836752008732533L;
 
     /**
-     * Constructor.
+     * Constructs a new property map.
      *
      * @param properties   A {@link PropertyHashMap} with initial contents.
      * @param fieldCount   Number of fields in use.
      * @param fieldMaximum Number of fields available.
      * @param spillLength  Number of spill slots used.
-     * @param containsArrayKeys True if properties contain numeric keys
      */
-    private PropertyMap(final PropertyHashMap properties, final String className, final int fieldCount,
-                        final int fieldMaximum, final int spillLength, final boolean containsArrayKeys) {
+    private PropertyMap(final PropertyHashMap properties, final int flags, final String className,
+                        final int fieldCount, final int fieldMaximum, final int spillLength) {
         this.properties   = properties;
         this.className    = className;
         this.fieldCount   = fieldCount;
         this.fieldMaximum = fieldMaximum;
         this.spillLength  = spillLength;
-        if (containsArrayKeys) {
-            setContainsArrayKeys();
-        }
+        this.flags        = flags;
+        this.softReferenceDerivationLimit = INITIAL_SOFT_REFERENCE_DERIVATION_LIMIT;
 
         if (Context.DEBUG) {
-            count++;
+            count.increment();
         }
     }
 
     /**
-     * Cloning constructor.
+     * Constructs a clone of {@code propertyMap} with changed properties, flags, or boundaries.
      *
      * @param propertyMap Existing property map.
      * @param properties  A {@link PropertyHashMap} with a new set of properties.
      */
-    private PropertyMap(final PropertyMap propertyMap, final PropertyHashMap properties) {
+    private PropertyMap(final PropertyMap propertyMap, final PropertyHashMap properties, final int flags, final int fieldCount, final int spillLength, final int softReferenceDerivationLimit) {
         this.properties   = properties;
-        this.flags        = propertyMap.flags;
-        this.spillLength  = propertyMap.spillLength;
-        this.fieldCount   = propertyMap.fieldCount;
+        this.flags        = flags;
+        this.spillLength  = spillLength;
+        this.fieldCount   = fieldCount;
         this.fieldMaximum = propertyMap.fieldMaximum;
+        this.className    = propertyMap.className;
         // 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;
+        this.sharedProtoMap = propertyMap.sharedProtoMap;
+        this.softReferenceDerivationLimit = softReferenceDerivationLimit;
 
         if (Context.DEBUG) {
-            count++;
-            clonedCount++;
+            count.increment();
+            clonedCount.increment();
         }
     }
 
     /**
-     * Cloning constructor.
+     * Constructs an exact clone of {@code propertyMap}.
      *
      * @param propertyMap Existing property map.
       */
-    private PropertyMap(final PropertyMap propertyMap) {
-        this(propertyMap, propertyMap.properties);
+    protected PropertyMap(final PropertyMap propertyMap) {
+        this(propertyMap, propertyMap.properties, propertyMap.flags, propertyMap.fieldCount, propertyMap.spillLength, propertyMap.softReferenceDerivationLimit);
     }
 
     private void writeObject(final ObjectOutputStream out) throws IOException {
@@ -182,7 +201,7 @@
      */
     public static PropertyMap newMap(final Collection<Property> properties, final String className, final int fieldCount, final int fieldMaximum,  final int spillLength) {
         final PropertyHashMap newProperties = EMPTY_HASHMAP.immutableAdd(properties);
-        return new PropertyMap(newProperties, className, fieldCount, fieldMaximum, spillLength, false);
+        return new PropertyMap(newProperties, 0, className, fieldCount, fieldMaximum, spillLength);
     }
 
     /**
@@ -199,12 +218,21 @@
     }
 
     /**
+     * Return a sharable empty map for the given object class.
+     * @param clazz the base object class
+     * @return New empty {@link PropertyMap}.
+     */
+    public static PropertyMap newMap(final Class<? extends ScriptObject> clazz) {
+        return new PropertyMap(EMPTY_HASHMAP, 0, clazz.getName(), 0, 0, 0);
+    }
+
+    /**
      * Return a sharable empty map.
      *
      * @return New empty {@link PropertyMap}.
      */
     public static PropertyMap newMap() {
-        return new PropertyMap(EMPTY_HASHMAP, JO.class.getName(), 0, 0, 0, false);
+        return newMap(JO.class);
     }
 
     /**
@@ -217,12 +245,12 @@
     }
 
     /**
-     * Get the listeners of this map, or null if none exists
+     * Get the number of listeners of this map
      *
-     * @return the listeners
+     * @return the number of listeners
      */
-    public PropertyListeners getListeners() {
-        return listeners;
+    public int getListenerCount() {
+        return listeners == null ? 0 : listeners.getListenerCount();
     }
 
     /**
@@ -243,9 +271,12 @@
      * A new property is being added.
      *
      * @param property The new Property added.
+     * @param isSelf was the property added to this map?
      */
-    public void propertyAdded(final Property property) {
-        invalidateProtoGetSwitchPoint(property);
+    public void propertyAdded(final Property property, final boolean isSelf) {
+        if (!isSelf) {
+            invalidateProtoSwitchPoint(property.getKey());
+        }
         if (listeners != null) {
             listeners.propertyAdded(property);
         }
@@ -255,9 +286,12 @@
      * An existing property is being deleted.
      *
      * @param property The property being deleted.
+     * @param isSelf was the property deleted from this map?
      */
-    public void propertyDeleted(final Property property) {
-        invalidateProtoGetSwitchPoint(property);
+    public void propertyDeleted(final Property property, final boolean isSelf) {
+        if (!isSelf) {
+            invalidateProtoSwitchPoint(property.getKey());
+        }
         if (listeners != null) {
             listeners.propertyDeleted(property);
         }
@@ -268,9 +302,12 @@
      *
      * @param oldProperty The old property
      * @param newProperty The new property
+     * @param isSelf was the property modified on this map?
      */
-    public void propertyModified(final Property oldProperty, final Property newProperty) {
-        invalidateProtoGetSwitchPoint(oldProperty);
+    public void propertyModified(final Property oldProperty, final Property newProperty, final boolean isSelf) {
+        if (!isSelf) {
+            invalidateProtoSwitchPoint(oldProperty.getKey());
+        }
         if (listeners != null) {
             listeners.propertyModified(oldProperty, newProperty);
         }
@@ -278,9 +315,15 @@
 
     /**
      * The prototype of an object associated with this {@link PropertyMap} is changed.
+     *
+     * @param isSelf was the prototype changed on the object using this map?
      */
-    public void protoChanged() {
-        invalidateAllProtoGetSwitchPoints();
+    public void protoChanged(final boolean isSelf) {
+        if (!isSelf) {
+            invalidateAllProtoSwitchPoints();
+        } else if (sharedProtoMap != null) {
+            sharedProtoMap.invalidateSwitchPoint();
+        }
         if (listeners != null) {
             listeners.protoChanged();
         }
@@ -293,14 +336,14 @@
      * @return A shared {@link SwitchPoint} for the property.
      */
     public synchronized SwitchPoint getSwitchPoint(final String key) {
-        if (protoGetSwitches == null) {
-            protoGetSwitches = new HashMap<>();
+        if (protoSwitches == null) {
+            protoSwitches = new HashMap<>();
         }
 
-        SwitchPoint switchPoint = protoGetSwitches.get(key);
+        SwitchPoint switchPoint = protoSwitches.get(key);
         if (switchPoint == null) {
             switchPoint = new SwitchPoint();
-            protoGetSwitches.put(key, switchPoint);
+            protoSwitches.put(key, switchPoint);
         }
 
         return switchPoint;
@@ -309,19 +352,17 @@
     /**
      * Indicate that a prototype property has changed.
      *
-     * @param property {@link Property} to invalidate.
+     * @param key {@link Property} key to invalidate.
      */
-    synchronized void invalidateProtoGetSwitchPoint(final Property property) {
-        if (protoGetSwitches != null) {
-
-            final String key = property.getKey();
-            final SwitchPoint sp = protoGetSwitches.get(key);
+    synchronized void invalidateProtoSwitchPoint(final String key) {
+        if (protoSwitches != null) {
+            final SwitchPoint sp = protoSwitches.get(key);
             if (sp != null) {
-                protoGetSwitches.remove(key);
+                protoSwitches.remove(key);
                 if (Context.DEBUG) {
-                    protoInvalidations++;
+                    protoInvalidations.increment();
                 }
-                SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
+                SwitchPoint.invalidateAll(new SwitchPoint[]{sp});
             }
         }
     }
@@ -329,13 +370,16 @@
     /**
      * Indicate that proto itself has changed in hierarchy somewhere.
      */
-    synchronized void invalidateAllProtoGetSwitchPoints() {
-        if (protoGetSwitches != null && !protoGetSwitches.isEmpty()) {
-            if (Context.DEBUG) {
-                protoInvalidations += protoGetSwitches.size();
+    synchronized void invalidateAllProtoSwitchPoints() {
+        if (protoSwitches != null) {
+            final int size = protoSwitches.size();
+            if (size > 0) {
+                if (Context.DEBUG) {
+                    protoInvalidations.add(size);
+                }
+                SwitchPoint.invalidateAll(protoSwitches.values().toArray(new SwitchPoint[size]));
+                protoSwitches.clear();
             }
-            SwitchPoint.invalidateAll(protoGetSwitches.values().toArray(new SwitchPoint[protoGetSwitches.values().size()]));
-            protoGetSwitches.clear();
         }
     }
 
@@ -350,7 +394,7 @@
      * @return New {@link PropertyMap} with {@link Property} added.
      */
     PropertyMap addPropertyBind(final AccessorProperty property, final Object bindTo) {
-        // No need to store bound property in the history as bound properties can't be reused.
+        // We must not store bound property in the history as bound properties can't be reused.
         return addPropertyNoHistory(new AccessorProperty(property, bindTo));
     }
 
@@ -363,19 +407,20 @@
         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();
-        }
+    private int newSpillLength(final Property newProperty) {
+        return newProperty.isSpill() ? Math.max(spillLength, newProperty.getSlot() + 1) : spillLength;
     }
 
-    // Update the free slots bitmap for a property that has been deleted and/or added.
+    private int newFieldCount(final Property newProperty) {
+        return !newProperty.isSpill() ? Math.max(fieldCount, newProperty.getSlot() + 1) : fieldCount;
+    }
+
+    private int newFlags(final Property newProperty) {
+        return isValidArrayIndex(getArrayIndex(newProperty.getKey())) ? flags | CONTAINS_ARRAY_KEYS : flags;
+    }
+
+    // Update the free slots bitmap for a property that has been deleted and/or added. This method is not synchronized
+    // as it is always invoked on a newly created instance.
     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;
@@ -406,16 +451,9 @@
      * @param property {@link Property} being added.
      * @return New {@link PropertyMap} with {@link Property} added.
      */
-    public PropertyMap addPropertyNoHistory(final Property property) {
-        if (listeners != null) {
-            listeners.propertyAdded(property);
-        }
-        final PropertyHashMap newProperties = properties.immutableAdd(property);
-        final PropertyMap newMap = new PropertyMap(this, newProperties);
-        newMap.updateFlagsAndBoundaries(property);
-        newMap.updateFreeSlots(null, property);
-
-        return newMap;
+    public final PropertyMap addPropertyNoHistory(final Property property) {
+        propertyAdded(property, true);
+        return addPropertyInternal(property);
     }
 
     /**
@@ -425,23 +463,29 @@
      *
      * @return New {@link PropertyMap} with {@link Property} added.
      */
-    public PropertyMap addProperty(final Property property) {
-        if (listeners != null) {
-            listeners.propertyAdded(property);
-        }
+    public final synchronized PropertyMap addProperty(final Property property) {
+        propertyAdded(property, true);
         PropertyMap newMap = checkHistory(property);
 
         if (newMap == null) {
-            final PropertyHashMap newProperties = properties.immutableAdd(property);
-            newMap = new PropertyMap(this, newProperties);
+            newMap = addPropertyInternal(property);
             addToHistory(property, newMap);
-            newMap.updateFlagsAndBoundaries(property);
-            newMap.updateFreeSlots(null, property);
         }
 
         return newMap;
     }
 
+    private PropertyMap deriveMap(final PropertyHashMap newProperties, final int newFlags, final int newFieldCount, final int newSpillLength) {
+        return new PropertyMap(this, newProperties, newFlags, newFieldCount, newSpillLength, softReferenceDerivationLimit == 0 ? 0 : softReferenceDerivationLimit - 1);
+    }
+
+    private PropertyMap addPropertyInternal(final Property property) {
+        final PropertyHashMap newProperties = properties.immutableAdd(property);
+        final PropertyMap newMap = deriveMap(newProperties, newFlags(property), newFieldCount(property), newSpillLength(property));
+        newMap.updateFreeSlots(null, property);
+        return newMap;
+    }
+
     /**
      * Remove a property from a map. Cloning or using an existing map if available.
      *
@@ -449,10 +493,8 @@
      *
      * @return New {@link PropertyMap} with {@link Property} removed or {@code null} if not found.
      */
-    public PropertyMap deleteProperty(final Property property) {
-        if (listeners != null) {
-            listeners.propertyDeleted(property);
-        }
+    public final synchronized PropertyMap deleteProperty(final Property property) {
+        propertyDeleted(property, true);
         PropertyMap newMap = checkHistory(property);
         final String key = property.getKey();
 
@@ -463,13 +505,13 @@
             // 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 = deriveMap(newProperties, flags, fieldCount, spillLength - 1);
                 newMap.freeSlots = freeSlots;
             } else if (!isSpill && slot >= 0 && slot == fieldCount - 1) {
-                newMap = new PropertyMap(newProperties, className, fieldCount - 1, fieldMaximum, spillLength, containsArrayKeys());
+                newMap = deriveMap(newProperties, flags, fieldCount - 1, spillLength);
                 newMap.freeSlots = freeSlots;
             } else {
-                newMap = new PropertyMap(this, newProperties);
+                newMap = deriveMap(newProperties, flags, fieldCount, spillLength);
                 newMap.updateFreeSlots(property, null);
             }
             addToHistory(property, newMap);
@@ -486,13 +528,8 @@
      *
      * @return New {@link PropertyMap} with {@link Property} replaced.
      */
-    PropertyMap replaceProperty(final Property oldProperty, final Property newProperty) {
-        if (listeners != null) {
-            listeners.propertyModified(oldProperty, newProperty);
-        }
-        // Add replaces existing property.
-        final PropertyHashMap newProperties = properties.immutableReplace(oldProperty, newProperty);
-        final PropertyMap newMap = new PropertyMap(this, newProperties);
+    public final PropertyMap replaceProperty(final Property oldProperty, final Property newProperty) {
+        propertyModified(oldProperty, newProperty, true);
         /*
          * See ScriptObject.modifyProperty and ScriptObject.setUserAccessors methods.
          *
@@ -514,14 +551,17 @@
                 newProperty instanceof UserAccessorProperty :
             "arbitrary replaceProperty attempted " + sameType + " oldProperty=" + oldProperty.getClass() + " newProperty=" + newProperty.getClass() + " [" + oldProperty.getLocalType() + " => " + newProperty.getLocalType() + "]";
 
-        newMap.flags = flags;
-
         /*
          * 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.
          */
+        final int newSpillLength = sameType ? spillLength : Math.max(spillLength, newProperty.getSlot() + 1);
+
+        // Add replaces existing property.
+        final PropertyHashMap newProperties = properties.immutableReplace(oldProperty, newProperty);
+        final PropertyMap newMap = deriveMap(newProperties, flags, fieldCount, newSpillLength);
+
         if (!sameType) {
-            newMap.spillLength = Math.max(spillLength, newProperty.getSlot() + 1);
             newMap.updateFreeSlots(oldProperty, newProperty);
         }
         return newMap;
@@ -537,7 +577,7 @@
      * @param propertyFlags attribute flags of the property
      * @return the newly created UserAccessorProperty
      */
-    public UserAccessorProperty newUserAccessors(final String key, final int propertyFlags) {
+    public final UserAccessorProperty newUserAccessors(final String key, final int propertyFlags) {
         return new UserAccessorProperty(key, propertyFlags, getFreeSpillSlot());
     }
 
@@ -548,7 +588,7 @@
      *
      * @return {@link Property} matching key.
      */
-    public Property findProperty(final String key) {
+    public final Property findProperty(final String key) {
         return properties.find(key);
     }
 
@@ -559,12 +599,12 @@
      *
      * @return New {@link PropertyMap} with added properties.
      */
-    public PropertyMap addAll(final PropertyMap other) {
+    public final PropertyMap addAll(final PropertyMap other) {
         assert this != other : "adding property map to itself";
         final Property[] otherProperties = other.properties.getProperties();
         final PropertyHashMap newProperties = properties.immutableAdd(otherProperties);
 
-        final PropertyMap newMap = new PropertyMap(this, newProperties);
+        final PropertyMap newMap = deriveMap(newProperties, flags, fieldCount, spillLength);
         for (final Property property : otherProperties) {
             // This method is only safe to use with non-slotted, native getter/setter properties
             assert property.getSlot() == -1;
@@ -579,19 +619,26 @@
      *
      * @return Properties as an array.
      */
-    public Property[] getProperties() {
+    public final Property[] getProperties() {
         return properties.getProperties();
     }
 
     /**
+     * Return the name of the class of objects using this property map.
+     *
+     * @return class name of owner objects.
+     */
+    public final String getClassName() {
+        return className;
+    }
+
+    /**
      * Prevents the map from having additional properties.
      *
      * @return New map with {@link #NOT_EXTENSIBLE} flag set.
      */
     PropertyMap preventExtensions() {
-        final PropertyMap newMap = new PropertyMap(this);
-        newMap.flags |= NOT_EXTENSIBLE;
-        return newMap;
+        return deriveMap(properties, flags | NOT_EXTENSIBLE, fieldCount, spillLength);
     }
 
     /**
@@ -607,10 +654,7 @@
             newProperties = newProperties.immutableAdd(oldProperty.addFlags(Property.NOT_CONFIGURABLE));
         }
 
-        final PropertyMap newMap = new PropertyMap(this, newProperties);
-        newMap.flags |= NOT_EXTENSIBLE;
-
-        return newMap;
+        return deriveMap(newProperties, flags | NOT_EXTENSIBLE, fieldCount, spillLength);
     }
 
     /**
@@ -632,10 +676,7 @@
             newProperties = newProperties.immutableAdd(oldProperty.addFlags(propertyFlags));
         }
 
-        final PropertyMap newMap = new PropertyMap(this, newProperties);
-        newMap.flags |= NOT_EXTENSIBLE;
-
-        return newMap;
+        return deriveMap(newProperties, flags | NOT_EXTENSIBLE, fieldCount, spillLength);
     }
 
     /**
@@ -691,7 +732,7 @@
         }
 
         if (Context.DEBUG && cachedMap != null) {
-            protoHistoryHit++;
+            protoHistoryHit.increment();
         }
 
         return cachedMap;
@@ -722,7 +763,7 @@
             history = new WeakHashMap<>();
         }
 
-        history.put(property, new SoftReference<>(newMap));
+        history.put(property, softReferenceDerivationLimit == 0 ? new WeakReference<>(newMap) : new SoftReference<>(newMap));
     }
 
     /**
@@ -735,12 +776,12 @@
     private PropertyMap checkHistory(final Property property) {
 
         if (history != null) {
-            final SoftReference<PropertyMap> ref = history.get(property);
+            final Reference<PropertyMap> ref = history.get(property);
             final PropertyMap historicMap = ref == null ? null : ref.get();
 
             if (historicMap != null) {
                 if (Context.DEBUG) {
-                    historyHit++;
+                    historyHit.increment();
                 }
 
                 return historicMap;
@@ -807,13 +848,6 @@
     }
 
     /**
-     * Flag this object as having array keys in defined properties
-     */
-    private void setContainsArrayKeys() {
-        flags |= CONTAINS_ARRAY_KEYS;
-    }
-
-    /**
      * Test to see if {@link PropertyMap} is extensible.
      *
      * @return {@code true} if {@link PropertyMap} can be added to.
@@ -881,23 +915,82 @@
      * @param newProto New prototype object to replace oldProto.
      * @return New {@link PropertyMap} with prototype changed.
      */
-    public PropertyMap changeProto(final ScriptObject newProto) {
-
+    public synchronized PropertyMap changeProto(final ScriptObject newProto) {
         final PropertyMap nextMap = checkProtoHistory(newProto);
         if (nextMap != null) {
             return nextMap;
         }
 
         if (Context.DEBUG) {
-            setProtoNewMapCount++;
+            setProtoNewMapCount.increment();
         }
 
-        final PropertyMap newMap = new PropertyMap(this);
+        final PropertyMap newMap = makeUnsharedCopy();
         addToProtoHistory(newProto, newMap);
 
         return newMap;
     }
 
+    /**
+     * Make a copy of this property map with the shared prototype field set to null. Note that this is
+     * only necessary for shared maps of top-level objects. Shared prototype maps represented by
+     * {@link SharedPropertyMap} are automatically converted to plain property maps when they evolve.
+     *
+     * @return a copy with the shared proto map unset
+     */
+    PropertyMap makeUnsharedCopy() {
+        final PropertyMap newMap = new PropertyMap(this);
+        newMap.sharedProtoMap = null;
+        return newMap;
+    }
+
+    /**
+     * Set a reference to the expected parent prototype map. This is used for class-like
+     * structures where we only want to use a top-level property map if all of the
+     * prototype property maps have not been modified.
+     *
+     * @param protoMap weak reference to the prototype property map
+     */
+    void setSharedProtoMap(final SharedPropertyMap protoMap) {
+        sharedProtoMap = protoMap;
+    }
+
+    /**
+     * Get the expected prototype property map if it is known, or null.
+     *
+     * @return parent map or null
+     */
+    public PropertyMap getSharedProtoMap() {
+        return sharedProtoMap;
+    }
+
+    /**
+     * Returns {@code true} if this map has been used as a shared prototype map (i.e. as a prototype
+     * for a JavaScript constructor function) and has not had properties added, deleted or replaced since then.
+     * @return true if this is a valid shared prototype map
+     */
+    boolean isValidSharedProtoMap() {
+        return false;
+    }
+
+    /**
+     * Returns the shared prototype switch point, or null if this is not a shared prototype map.
+     * @return the shared prototype switch point, or null
+     */
+    SwitchPoint getSharedProtoSwitchPoint() {
+        return null;
+    }
+
+    /**
+     * Return true if this map has a shared prototype map which has either been invalidated or does
+     * not match the map of {@code proto}.
+     * @param prototype the prototype object
+     * @return true if this is an invalid shared map for {@code prototype}
+     */
+    boolean isInvalidSharedMapFor(final ScriptObject prototype) {
+        return sharedProtoMap != null
+                && (!sharedProtoMap.isValidSharedProtoMap() || prototype == null || sharedProtoMap != prototype.getMap());
+    }
 
     /**
      * {@link PropertyMap} iterator.
@@ -978,10 +1071,10 @@
            for (final Property p : map0.getProperties()) {
                final Property p2 = map1.findProperty(p.getKey());
                if (p2 == null) {
-                   sb.append("FIRST ONLY : [" + p + "]");
+                   sb.append("FIRST ONLY : [").append(p).append("]");
                    found = true;
                } else if (p2 != p) {
-                   sb.append("DIFFERENT  : [" + p + "] != [" + p2 + "]");
+                   sb.append("DIFFERENT  : [").append(p).append("] != [").append(p2).append("]");
                    found = true;
                }
            }
@@ -989,7 +1082,7 @@
            for (final Property p2 : map1.getProperties()) {
                final Property p1 = map0.findProperty(p2.getKey());
                if (p1 == null) {
-                   sb.append("SECOND ONLY: [" + p2 + "]");
+                   sb.append("SECOND ONLY: [").append(p2).append("]");
                    found = true;
                }
            }
@@ -1009,52 +1102,62 @@
     }
 
     // counters updated only in debug mode
-    private static int count;
-    private static int clonedCount;
-    private static int historyHit;
-    private static int protoInvalidations;
-    private static int protoHistoryHit;
-    private static int setProtoNewMapCount;
+    private static LongAdder count;
+    private static LongAdder clonedCount;
+    private static LongAdder historyHit;
+    private static LongAdder protoInvalidations;
+    private static LongAdder protoHistoryHit;
+    private static LongAdder setProtoNewMapCount;
+    static {
+        if (Context.DEBUG) {
+            count = new LongAdder();
+            clonedCount = new LongAdder();
+            historyHit = new LongAdder();
+            protoInvalidations = new LongAdder();
+            protoHistoryHit = new LongAdder();
+            setProtoNewMapCount = new LongAdder();
+        }
+    }
 
     /**
      * @return Total number of maps.
      */
-    public static int getCount() {
-        return count;
+    public static long getCount() {
+        return count.longValue();
     }
 
     /**
      * @return The number of maps that were cloned.
      */
-    public static int getClonedCount() {
-        return clonedCount;
+    public static long getClonedCount() {
+        return clonedCount.longValue();
     }
 
     /**
      * @return The number of times history was successfully used.
      */
-    public static int getHistoryHit() {
-        return historyHit;
+    public static long getHistoryHit() {
+        return historyHit.longValue();
     }
 
     /**
      * @return The number of times prototype changes caused invalidation.
      */
-    public static int getProtoInvalidations() {
-        return protoInvalidations;
+    public static long getProtoInvalidations() {
+        return protoInvalidations.longValue();
     }
 
     /**
      * @return The number of times proto history was successfully used.
      */
-    public static int getProtoHistoryHit() {
-        return protoHistoryHit;
+    public static long getProtoHistoryHit() {
+        return protoHistoryHit.longValue();
     }
 
     /**
      * @return The number of times prototypes were modified.
      */
-    public static int getSetProtoNewMapCount() {
-        return setProtoNewMapCount;
+    public static long getSetProtoNewMapCount() {
+        return setProtoNewMapCount.longValue();
     }
 }
diff --git a/src/jdk/nashorn/internal/objects/PrototypeObject.java b/src/jdk/nashorn/internal/runtime/PrototypeObject.java
similarity index 87%
rename from src/jdk/nashorn/internal/objects/PrototypeObject.java
rename to src/jdk/nashorn/internal/runtime/PrototypeObject.java
index b119dad..f4c1b5f 100644
--- a/src/jdk/nashorn/internal/objects/PrototypeObject.java
+++ b/src/jdk/nashorn/internal/runtime/PrototypeObject.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.internal.objects;
+package jdk.nashorn.internal.runtime;
 
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
@@ -31,17 +31,12 @@
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.util.ArrayList;
-import jdk.nashorn.internal.runtime.AccessorProperty;
-import jdk.nashorn.internal.runtime.Property;
-import jdk.nashorn.internal.runtime.PropertyMap;
-import jdk.nashorn.internal.runtime.ScriptFunction;
-import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.objects.Global;
 
 /**
  * Instances of this class serve as "prototype" object for script functions.
  * The purpose is to expose "constructor" property from "prototype". Also, nasgen
  * generated prototype classes extend from this class.
- *
  */
 public class PrototypeObject extends ScriptObject {
     private static final PropertyMap map$;
@@ -61,7 +56,10 @@
         super(global.getObjectPrototype(), map != map$? map.addAll(map$) : map$);
     }
 
-    PrototypeObject() {
+    /**
+     * Prototype constructor
+     */
+    protected PrototypeObject() {
         this(Global.instance(), map$);
     }
 
@@ -70,11 +68,16 @@
      *
      * @param map property map
      */
-    PrototypeObject(final PropertyMap map) {
+    protected PrototypeObject(final PropertyMap map) {
         this(Global.instance(), map);
     }
 
-    PrototypeObject(final ScriptFunction func) {
+    /**
+     * PropertyObject constructor
+     *
+     * @param func constructor function
+     */
+    protected PrototypeObject(final ScriptFunction func) {
         this(Global.instance(), map$);
         this.constructor = func;
     }
@@ -84,7 +87,7 @@
      * @param self self reference
      * @return constructor, probably, but not necessarily, a {@link ScriptFunction}
      */
-    static Object getConstructor(final Object self) {
+    public static Object getConstructor(final Object self) {
         return (self instanceof PrototypeObject) ?
             ((PrototypeObject)self).getConstructor() :
             UNDEFINED;
@@ -95,7 +98,7 @@
      * @param self self reference
      * @param constructor constructor, probably, but not necessarily, a {@link ScriptFunction}
      */
-    static void setConstructor(final Object self, final Object constructor) {
+    public static void setConstructor(final Object self, final Object constructor) {
         if (self instanceof PrototypeObject) {
             ((PrototypeObject)self).setConstructor(constructor);
         }
diff --git a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
index 06414ed..41be82a 100644
--- a/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
+++ b/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
@@ -26,30 +26,44 @@
 package jdk.nashorn.internal.runtime;
 
 import static jdk.nashorn.internal.lookup.Lookup.MH;
+
 import java.io.IOException;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
+import java.util.IdentityHashMap;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
 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.Namespace;
-import jdk.nashorn.internal.codegen.ObjectClassGenerator.AllocatorDescriptor;
 import jdk.nashorn.internal.codegen.OptimisticTypesPersistence;
 import jdk.nashorn.internal.codegen.TypeMap;
 import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.Block;
+import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.LexicalContext;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.SwitchNode;
+import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.ir.TryNode;
+import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.parser.Parser;
 import jdk.nashorn.internal.parser.Token;
@@ -57,6 +71,7 @@
 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 a subclass that represents a script function that may be regenerated,
  * for example with specialization based on call site types, or lazily generated.
@@ -68,6 +83,8 @@
     /** Prefix used for all recompiled script classes */
     public static final String RECOMPILATION_PREFIX = "Recompilation$";
 
+    private static final ExecutorService astSerializerExecutorService = createAstSerializerExecutorService();
+
     /** Unique function node id for this function node */
     private final int functionNodeId;
 
@@ -79,8 +96,12 @@
     /** Source from which FunctionNode was parsed. */
     private transient Source source;
 
-    /** Serialized, compressed form of the AST. Used by split functions as they can't be reparsed from source. */
-    private final byte[] serializedAst;
+    /**
+     * Cached form of the AST. Either a {@code SerializedAst} object used by split functions as they can't be
+     * reparsed from source, or a soft reference to a {@code FunctionNode} for other functions (it is safe
+     * to be cleared as they can be reparsed).
+     */
+    private volatile Object cachedAst;
 
     /** Token of this function within the source. */
     private final long token;
@@ -99,7 +120,7 @@
     private final Object endParserState;
 
     /** Code installer used for all further recompilation/specialization of this ScriptFunction */
-    private transient CodeInstaller<ScriptEnvironment> installer;
+    private transient CodeInstaller installer;
 
     private final Map<Integer, RecompilableScriptFunctionData> nestedFunctions;
 
@@ -126,20 +147,18 @@
      *
      * @param functionNode        functionNode that represents this function code
      * @param installer           installer for code regeneration versions of this function
-     * @param allocationDescriptor descriptor for the allocation behavior when this function is used as a constructor
+     * @param allocationStrategy  strategy for the allocation behavior when this function is used as a constructor
      * @param nestedFunctions     nested function map
      * @param externalScopeDepths external scope depths
      * @param internalSymbols     internal symbols to method, defined in its scope
-     * @param serializedAst       a serialized AST representation. Normally only used for split functions.
      */
     public RecompilableScriptFunctionData(
         final FunctionNode functionNode,
-        final CodeInstaller<ScriptEnvironment> installer,
-        final AllocatorDescriptor allocationDescriptor,
+        final CodeInstaller installer,
+        final AllocationStrategy allocationStrategy,
         final Map<Integer, RecompilableScriptFunctionData> nestedFunctions,
         final Map<String, Integer> externalScopeDepths,
-        final Set<String> internalSymbols,
-        final byte[] serializedAst) {
+        final Set<String> internalSymbols) {
 
         super(functionName(functionNode),
               Math.min(functionNode.getParameters().size(), MAX_ARITY),
@@ -153,7 +172,7 @@
         this.endParserState      = functionNode.getEndParserState();
         this.token               = tokenFor(functionNode);
         this.installer           = installer;
-        this.allocationStrategy  = AllocationStrategy.get(allocationDescriptor);
+        this.allocationStrategy  = allocationStrategy;
         this.nestedFunctions     = smallMap(nestedFunctions);
         this.externalScopeDepths = smallMap(externalScopeDepths);
         this.internalSymbols     = smallSet(new HashSet<>(internalSymbols));
@@ -163,7 +182,6 @@
             nfn.setParent(this);
         }
 
-        this.serializedAst = serializedAst;
         createLogger();
     }
 
@@ -246,7 +264,7 @@
      * @return parent data, or null if non exists and also null IF UNKNOWN.
      */
     public RecompilableScriptFunctionData getParent() {
-       return parent;
+        return parent;
     }
 
     void setParent(final RecompilableScriptFunctionData parent) {
@@ -268,7 +286,7 @@
      * @param src source
      * @param inst code installer
      */
-    public void initTransients(final Source src, final CodeInstaller<ScriptEnvironment> inst) {
+    public void initTransients(final Source src, final CodeInstaller inst) {
         if (this.source == null && this.installer == null) {
             this.source    = src;
             this.installer = inst;
@@ -344,12 +362,15 @@
         if (functionNode.isVarArg()) {
             flags |= IS_VARIABLE_ARITY;
         }
+        if (functionNode.getKind() == FunctionNode.Kind.GETTER || functionNode.getKind() == FunctionNode.Kind.SETTER) {
+            flags |= IS_PROPERTY_ACCESSOR;
+        }
         return flags;
     }
 
     @Override
-    PropertyMap getAllocatorMap() {
-        return allocationStrategy.getAllocatorMap();
+    PropertyMap getAllocatorMap(final ScriptObject prototype) {
+        return allocationStrategy.getAllocatorMap(prototype);
     }
 
     @Override
@@ -357,13 +378,11 @@
         return allocationStrategy.allocate(map);
     }
 
-    boolean isSerialized() {
-        return serializedAst != null;
-    }
-
     FunctionNode reparse() {
-        if (isSerialized()) {
-            return deserialize();
+        final FunctionNode cachedFunction = getCachedAst();
+        if (cachedFunction != null) {
+            assert cachedFunction.isCached();
+            return cachedFunction;
         }
 
         final int descPosition = Token.descPosition(token);
@@ -384,14 +403,111 @@
         parser.setReparsedFunction(this);
 
         final FunctionNode program = parser.parse(CompilerConstants.PROGRAM.symbolName(), descPosition,
-                Token.descLength(token), true);
+                Token.descLength(token), isPropertyAccessor());
         // 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);
     }
 
-    private FunctionNode deserialize() {
-        final ScriptEnvironment env = installer.getOwner();
+    private FunctionNode getCachedAst() {
+        final Object lCachedAst = cachedAst;
+        // Are we softly caching the AST?
+        if (lCachedAst instanceof Reference<?>) {
+            final FunctionNode fn = (FunctionNode)((Reference<?>)lCachedAst).get();
+            if (fn != null) {
+                // Yes we are - this is fast
+                return cloneSymbols(fn);
+            }
+        // Are we strongly caching a serialized AST (for split functions only)?
+        } else if (lCachedAst instanceof SerializedAst) {
+            final SerializedAst serializedAst = (SerializedAst)lCachedAst;
+            // Even so, are we also softly caching the AST?
+            final FunctionNode cachedFn = serializedAst.cachedAst.get();
+            if (cachedFn != null) {
+                // Yes we are - this is fast
+                return cloneSymbols(cachedFn);
+            }
+            final FunctionNode deserializedFn = deserialize(serializedAst.serializedAst);
+            // Softly cache after deserialization, maybe next time we won't need to deserialize
+            serializedAst.cachedAst = new SoftReference<>(deserializedFn);
+            return deserializedFn;
+        }
+        // No cached representation; return null for reparsing
+        return null;
+    }
+
+    /**
+     * Sets the AST to cache in this function
+     * @param astToCache the new AST to cache
+     */
+    public void setCachedAst(final FunctionNode astToCache) {
+        assert astToCache.getId() == functionNodeId; // same function
+        assert !(cachedAst instanceof SerializedAst); // Can't overwrite serialized AST
+
+        final boolean isSplit = astToCache.isSplit();
+        // If we're caching a split function, we're doing it in the eager pass, hence there can be no other
+        // cached representation already. In other words, isSplit implies cachedAst == null.
+        assert !isSplit || cachedAst == null; //
+
+        final FunctionNode symbolClonedAst = cloneSymbols(astToCache);
+        final Reference<FunctionNode> ref = new SoftReference<>(symbolClonedAst);
+        cachedAst = ref;
+
+        // Asynchronously serialize split functions.
+        if (isSplit) {
+            astSerializerExecutorService.execute(new Runnable() {
+                @Override
+                public void run() {
+                    cachedAst = new SerializedAst(symbolClonedAst, ref);
+                }
+            });
+        }
+    }
+
+    /**
+     * Creates the AST serializer executor service used for in-memory serialization of split functions' ASTs.
+     * It is created with an unbounded queue (so it can queue any number of pending tasks). Its core and max
+     * threads is the same, but they are all allowed to time out so when there's no work, they can all go
+     * away. The threads will be daemons, and they will time out if idle for a minute. Their priority is also
+     * slightly lower than normal priority as we'd prefer the CPU to keep running the program; serializing
+     * split function is a memory conservation measure (it allows us to release the AST), it can wait a bit.
+     * @return an executor service with above described characteristics.
+     */
+    private static ExecutorService createAstSerializerExecutorService() {
+        final int threads = Math.max(1, Options.getIntProperty("nashorn.serialize.threads", Runtime.getRuntime().availableProcessors() / 2));
+        final ThreadPoolExecutor service = new ThreadPoolExecutor(threads, threads, 1L, TimeUnit.MINUTES, new LinkedBlockingDeque<Runnable>(),
+                new ThreadFactory() {
+                    @Override
+                    public Thread newThread(final Runnable r) {
+                        final Thread t = new Thread(r, "Nashorn AST Serializer");
+                        t.setDaemon(true);
+                        t.setPriority(Thread.NORM_PRIORITY - 1);
+                        return t;
+                    }
+                });
+        service.allowCoreThreadTimeOut(true);
+        return service;
+    }
+
+    /**
+     * A tuple of a serialized AST and a soft reference to a deserialized AST. This is used to cache split
+     * functions. Since split functions are altered from their source form, they can't be reparsed from
+     * source. While we could just use the {@code byte[]} representation in {@link RecompilableScriptFunctionData#cachedAst}
+     * we're using this tuple instead to also keep a deserialized AST around in memory to cut down on
+     * deserialization costs.
+     */
+    private static class SerializedAst {
+        private final byte[] serializedAst;
+        private volatile Reference<FunctionNode> cachedAst;
+
+        SerializedAst(final FunctionNode fn, final Reference<FunctionNode> cachedAst) {
+            this.serializedAst = AstSerializer.serialize(fn);
+            this.cachedAst = cachedAst;
+        }
+    }
+
+    private FunctionNode deserialize(final byte[] serializedAst) {
+        final ScriptEnvironment env = installer.getContext().getEnv();
         final Timing timing = env._timing;
         final long t1 = System.nanoTime();
         try {
@@ -401,6 +517,107 @@
         }
     }
 
+    private FunctionNode cloneSymbols(final FunctionNode fn) {
+        final IdentityHashMap<Symbol, Symbol> symbolReplacements = new IdentityHashMap<>();
+        final boolean cached = fn.isCached();
+        // blockDefinedSymbols is used to re-mark symbols defined outside the function as global. We only
+        // need to do this when we cache an eagerly parsed function (which currently means a split one, as we
+        // don't cache non-split functions from the eager pass); those already cached, or those not split
+        // don't need this step.
+        final Set<Symbol> blockDefinedSymbols = fn.isSplit() && !cached ? Collections.newSetFromMap(new IdentityHashMap<Symbol, Boolean>()) : null;
+        FunctionNode newFn = (FunctionNode)fn.accept(new SimpleNodeVisitor() {
+
+            private Symbol getReplacement(final Symbol original) {
+                if (original == null) {
+                    return null;
+                }
+                final Symbol existingReplacement = symbolReplacements.get(original);
+                if (existingReplacement != null) {
+                    return existingReplacement;
+                }
+                final Symbol newReplacement = original.clone();
+                symbolReplacements.put(original, newReplacement);
+                return newReplacement;
+            }
+
+            @Override
+            public Node leaveIdentNode(final IdentNode identNode) {
+                final Symbol oldSymbol = identNode.getSymbol();
+                if (oldSymbol != null) {
+                    final Symbol replacement = getReplacement(oldSymbol);
+                    return identNode.setSymbol(replacement);
+                }
+                return identNode;
+            }
+
+            @Override
+            public Node leaveForNode(final ForNode forNode) {
+                return ensureUniqueLabels(forNode.setIterator(lc, getReplacement(forNode.getIterator())));
+            }
+
+            @Override
+            public Node leaveSwitchNode(final SwitchNode switchNode) {
+                return ensureUniqueLabels(switchNode.setTag(lc, getReplacement(switchNode.getTag())));
+            }
+
+            @Override
+            public Node leaveTryNode(final TryNode tryNode) {
+                return ensureUniqueLabels(tryNode.setException(lc, getReplacement(tryNode.getException())));
+            }
+
+            @Override
+            public boolean enterBlock(final Block block) {
+                for(final Symbol symbol: block.getSymbols()) {
+                    final Symbol replacement = getReplacement(symbol);
+                    if (blockDefinedSymbols != null) {
+                        blockDefinedSymbols.add(replacement);
+                    }
+                }
+                return true;
+            }
+
+            @Override
+            public Node leaveBlock(final Block block) {
+                return ensureUniqueLabels(block.replaceSymbols(lc, symbolReplacements));
+            }
+
+            @Override
+            public Node leaveFunctionNode(final FunctionNode functionNode) {
+                return functionNode.setParameters(lc, functionNode.visitParameters(this));
+            }
+
+            @Override
+            protected Node leaveDefault(final Node node) {
+                return ensureUniqueLabels(node);
+            };
+
+            private Node ensureUniqueLabels(final Node node) {
+                // If we're returning a cached AST, we must also ensure unique labels
+                return cached ? node.ensureUniqueLabels(lc) : node;
+            }
+        });
+
+        if (blockDefinedSymbols != null) {
+            // Mark all symbols not defined in blocks as globals
+            Block newBody = null;
+            for(final Symbol symbol: symbolReplacements.values()) {
+                if(!blockDefinedSymbols.contains(symbol)) {
+                    assert symbol.isScope(); // must be scope
+                    assert externalScopeDepths.containsKey(symbol.getName()); // must be known to us as an external
+                    // Register it in the function body symbol table as a new global symbol
+                    symbol.setFlags((symbol.getFlags() & ~Symbol.KINDMASK) | Symbol.IS_GLOBAL);
+                    if (newBody == null) {
+                        newBody = newFn.getBody().copyWithNewSymbols();
+                        newFn = newFn.setBody(null, newBody);
+                    }
+                    assert newBody.getExistingSymbol(symbol.getName()) == null; // must not be defined in the body already
+                    newBody.putSymbol(symbol);
+                }
+            }
+        }
+        return newFn.setCached(null);
+    }
+
     private boolean getFunctionFlag(final int flag) {
         return (functionFlags & flag) != 0;
     }
@@ -437,8 +654,8 @@
      * a new class loader with optimistic typing so that deoptimized code can get reclaimed by GC.
      * @return a code installer for installing new code.
      */
-    private CodeInstaller<ScriptEnvironment> getInstallerForNewCode() {
-        final ScriptEnvironment env = installer.getOwner();
+    private CodeInstaller getInstallerForNewCode() {
+        final ScriptEnvironment env = installer.getContext().getEnv();
         return env._optimistic_types || env._loader_per_compile ? installer.withNewLoader() : installer;
     }
 
@@ -448,15 +665,10 @@
         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(),
+        return Compiler.forOnDemandCompilation(
                 getInstallerForNewCode(),
                 functionNode.getSource(),  // source
-                context.getErrorManager(),
                 isStrict() | functionNode.isStrict(), // is strict
-                true,       // is on demand
                 this,       // compiledFunction, i.e. this RecompilableScriptFunctionData
                 typeMap,    // type map
                 getEffectiveInvalidatedProgramPoints(invalidatedProgramPoints, typeInformationFile), // invalidated program points
@@ -493,85 +705,34 @@
             log.info("Parameter type specialization of '", functionName, "' signature: ", actualCallSiteType);
         }
 
-        final boolean persistentCache = usePersistentCodeCache() && persist;
+        final boolean persistentCache = persist && usePersistentCodeCache();
         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 CodeInstaller<ScriptEnvironment> newInstaller = getInstallerForNewCode();
+            final CodeInstaller newInstaller = getInstallerForNewCode();
             final StoredScript script = newInstaller.loadScript(source, cacheKey);
 
             if (script != null) {
                 Compiler.updateCompilationId(script.getCompilationId());
-                return installStoredScript(script, newInstaller);
+                return script.installFunction(this, newInstaller);
             }
         }
 
         final FunctionNode fn = reparse();
         final Compiler compiler = getCompiler(fn, actualCallSiteType, runtimeScope);
         final FunctionNode compiledFn = compiler.compile(fn,
-                isSerialized() ? CompilationPhases.COMPILE_ALL_SERIALIZED : CompilationPhases.COMPILE_ALL);
+                fn.isCached() ? CompilationPhases.COMPILE_ALL_CACHED : CompilationPhases.COMPILE_ALL);
 
-        if (persist && !compiledFn.getFlag(FunctionNode.HAS_APPLY_TO_CALL_SPECIALIZATION)) {
+        if (persist && !compiledFn.hasApplyToCallSpecialization()) {
             compiler.persistClassInfo(cacheKey, compiledFn);
         }
         return new FunctionInitializer(compiledFn, compiler.getInvalidatedProgramPoints());
     }
 
-    private static Map<String, Class<?>> installStoredScriptClasses(final StoredScript script, final CodeInstaller<ScriptEnvironment> installer) {
-        final Map<String, Class<?>> installedClasses = new HashMap<>();
-        final Map<String, byte[]>   classBytes       = script.getClassBytes();
-        final String   mainClassName   = script.getMainClassName();
-        final byte[]   mainClassBytes  = classBytes.get(mainClassName);
-
-        final Class<?> mainClass       = installer.install(mainClassName, mainClassBytes);
-
-        installedClasses.put(mainClassName, mainClass);
-
-        for (final Map.Entry<String, byte[]> entry : classBytes.entrySet()) {
-            final String className = entry.getKey();
-            final byte[] bytecode = entry.getValue();
-
-            if (className.equals(mainClassName)) {
-                continue;
-            }
-
-            installedClasses.put(className, installer.install(className, bytecode));
-        }
-        return installedClasses;
-    }
-
-    /**
-     * Install this script using the given {@code installer}.
-     *
-     * @param script the compiled script
-     * @return the function initializer
-     */
-    private FunctionInitializer installStoredScript(final StoredScript script, final CodeInstaller<ScriptEnvironment> newInstaller) {
-        final Map<String, Class<?>> installedClasses = installStoredScriptClasses(script, newInstaller);
-
-        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());
-            }
-        }
-
-        newInstaller.initialize(installedClasses.values(), source, constants);
-        initializer.setCode(installedClasses.get(initializer.getClassName()));
-        return initializer;
-    }
-
     boolean usePersistentCodeCache() {
-        final ScriptEnvironment env = installer.getOwner();
-        return env._persistent_cache && env._optimistic_types;
+        return installer != null && installer.getContext().getEnv()._persistent_cache;
     }
 
     private MethodType explicitParams(final MethodType callSiteType) {
@@ -603,7 +764,7 @@
 
     private FunctionNode extractFunctionFromScript(final FunctionNode script) {
         final Set<FunctionNode> fns = new HashSet<>();
-        script.getBody().accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        script.getBody().accept(new SimpleNodeVisitor() {
             @Override
             public boolean enterFunctionNode(final FunctionNode fn) {
                 fns.add(fn);
@@ -646,19 +807,28 @@
      * by the compiler internals in Nashorn and is public for implementation reasons only. Attempting to invoke it
      * externally will result in an exception.
      *
-     * @param initializer FunctionInitializer for this data
+     * @param functionNode FunctionNode for this data
      */
-    public void initializeCode(final FunctionInitializer initializer) {
+    public void initializeCode(final FunctionNode functionNode) {
         // Since the method is public, we double-check that we aren't invoked with an inappropriate compile unit.
-        if(!code.isEmpty()) {
+        if (!code.isEmpty() || functionNode.getId() != functionNodeId || !functionNode.getCompileUnit().isInitializing(this, functionNode)) {
             throw new IllegalStateException(name);
         }
+        addCode(lookup(functionNode), null, null, functionNode.getFlags());
+    }
+
+    /**
+     * Initializes this function with the given function code initializer.
+     * @param initializer function code initializer
+     */
+    void initializeCode(final FunctionInitializer initializer) {
         addCode(lookup(initializer, true), 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);
+        assert noDuplicateCode(cfn) : "duplicate code";
         code.add(cfn);
         return cfn;
     }
@@ -724,15 +894,18 @@
     }
 
     @Override
-    synchronized CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) {
-        CompiledFunction existingBest = super.getBest(callSiteType, runtimeScope, forbidden);
+    synchronized CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden, final boolean linkLogicOkay) {
+        assert isValidCallSite(callSiteType) : callSiteType;
+
+        CompiledFunction existingBest = pickFunction(callSiteType, false);
+        if (existingBest == null) {
+            existingBest = pickFunction(callSiteType, true); // try vararg last
+        }
         if (existingBest == null) {
             existingBest = addCode(compileTypeSpecialization(callSiteType, runtimeScope, true), callSiteType);
         }
 
         assert existingBest != null;
-        //we are calling a vararg method with real args
-        boolean varArgWithRealArgs = 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
@@ -741,27 +914,18 @@
             if (best != null) {
                 return best;
             }
-            varArgWithRealArgs = true;
-        }
 
-        if (varArgWithRealArgs) {
             // special case: we had an apply to call, but we failed to make it fit.
             // Try to generate a specialized one for this callsite. It may
             // be another apply to call specialization, or it may not, but whatever
             // it is, it is a specialization that is guaranteed to fit
-            final FunctionInitializer fnInit = compileTypeSpecialization(callSiteType, runtimeScope, false);
-            existingBest = addCode(fnInit, callSiteType);
+            existingBest = addCode(compileTypeSpecialization(callSiteType, runtimeScope, false), callSiteType);
         }
 
         return existingBest;
     }
 
     @Override
-    boolean isRecompilable() {
-        return true;
-    }
-
-    @Override
     public boolean needsCallee() {
         return getFunctionFlag(FunctionNode.NEEDS_CALLEE);
     }
@@ -869,6 +1033,16 @@
         return newFn;
     }
 
+    // Make sure code does not contain a compiled function with the same signature as compiledFunction
+    private boolean noDuplicateCode(final CompiledFunction compiledFunction) {
+        for (final CompiledFunction cf : code) {
+            if (cf.type().equals(compiledFunction.type())) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
         in.defaultReadObject();
         createLogger();
diff --git a/src/jdk/nashorn/internal/runtime/Scope.java b/src/jdk/nashorn/internal/runtime/Scope.java
index eb7eb1f..9650f9c 100644
--- a/src/jdk/nashorn/internal/runtime/Scope.java
+++ b/src/jdk/nashorn/internal/runtime/Scope.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,30 +25,106 @@
 
 package jdk.nashorn.internal.runtime;
 
-import static jdk.nashorn.internal.codegen.CompilerConstants.interfaceCallNoLookup;
+import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
 
+import java.util.concurrent.atomic.LongAdder;
 import jdk.nashorn.internal.codegen.CompilerConstants;
 
 /**
- * Interface implemented by {@link ScriptObject}s that act as scope.
+ * A {@link ScriptObject} subclass for objects that act as scope.
  */
-public interface Scope {
+public class Scope extends ScriptObject {
+
+    /* This is used to store return state of split functions. */
+    private int splitState = -1;
+
+    /** This is updated only in debug mode - counts number of {@code ScriptObject} instances created that are scope */
+    private static final LongAdder count = Context.DEBUG ? new LongAdder() : null;
 
     /** Method handle that points to {@link Scope#getSplitState}. */
-    public static final CompilerConstants.Call GET_SPLIT_STATE = interfaceCallNoLookup(Scope.class, "getSplitState", int.class);
-
+    public static final CompilerConstants.Call GET_SPLIT_STATE = virtualCallNoLookup(Scope.class, "getSplitState", int.class);
     /** Method handle that points to {@link Scope#setSplitState(int)}. */
-    public static final CompilerConstants.Call SET_SPLIT_STATE = interfaceCallNoLookup(Scope.class, "setSplitState", void.class, int.class);
+    public static final CompilerConstants.Call SET_SPLIT_STATE = virtualCallNoLookup(Scope.class, "setSplitState", void.class, int.class);
+
+    /**
+     * Constructor
+     *
+     * @param map initial property map
+     */
+    public Scope(final PropertyMap map) {
+        super(map);
+        incrementCount();
+    }
+
+    /**
+     * Constructor
+     *
+     * @param proto parent scope
+     * @param map   initial property map
+     */
+    public Scope(final ScriptObject proto, final PropertyMap map) {
+        super(proto, map);
+        incrementCount();
+    }
+
+    /**
+     * Constructor
+     *
+     * @param map            property map
+     * @param primitiveSpill primitive spill array
+     * @param objectSpill    reference spill array
+     */
+    public Scope(final PropertyMap map, final long[] primitiveSpill, final Object[] objectSpill) {
+        super(map, primitiveSpill, objectSpill);
+        incrementCount();
+    }
+
+    @Override
+    public boolean isScope() {
+        return true;
+    }
+
+    @Override
+    boolean hasWithScope() {
+        for (ScriptObject obj = this; obj != null; obj = obj.getProto()) {
+            if (obj instanceof WithObject) {
+                return true;
+            }
+        }
+        return false;
+    }
 
     /**
      * Get the scope's split method state.
-     * @return the current state
+     *
+     * @return current split state
      */
-    public int getSplitState();
+    public int getSplitState() {
+        return splitState;
+    }
 
     /**
      * Set the scope's split method state.
-     * @param state the new state.
+     *
+     * @param state current split state
      */
-    public void setSplitState(int state);
+    public void setSplitState(final int state) {
+        splitState = state;
+    }
+
+    /**
+     * Get number of {@code Scope} instances created. If not running in debug
+     * mode this is always 0.
+     *
+     * @return number of scope ScriptObjects created
+     */
+    public static long getScopeCount() {
+        return count != null ? count.sum() : 0;
+    }
+
+    private static void incrementCount() {
+        if (Context.DEBUG) {
+            count.increment();
+        }
+    }
 }
diff --git a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
index c7fd019..b426480 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
@@ -46,6 +46,11 @@
  * and output and error writers, top level Namespace etc.
  */
 public final class ScriptEnvironment {
+    // Primarily intended to be used in test environments so that eager compilation tests work without an
+    // error when tested with optimistic compilation.
+    private static final boolean ALLOW_EAGER_COMPILATION_SILENT_OVERRIDE = Options.getBooleanProperty(
+            "nashorn.options.allowEagerCompilationSilentOverride", false);
+
     /** Output writer for this environment */
     private final PrintWriter out;
 
@@ -73,7 +78,7 @@
     /** Generate line number table in class files */
     public final boolean _debug_lines;
 
-    /** Package to which generated class files are added */
+    /** Directory in which source files and generated class files are dumped */
     public final String  _dest_dir;
 
     /** Display stack trace upon error, default is false */
@@ -237,8 +242,20 @@
         }
         _fx                   = options.getBoolean("fx");
         _global_per_engine    = options.getBoolean("global.per.engine");
-        _lazy_compilation     = options.getBoolean("lazy.compilation");
         _optimistic_types     = options.getBoolean("optimistic.types");
+        final boolean lazy_compilation = options.getBoolean("lazy.compilation");
+        if (!lazy_compilation && _optimistic_types) {
+            if (!ALLOW_EAGER_COMPILATION_SILENT_OVERRIDE) {
+                throw new IllegalStateException(
+                        ECMAErrors.getMessage(
+                                "config.error.eagerCompilationConflictsWithOptimisticTypes",
+                                options.getOptionTemplateByKey("lazy.compilation").getName(),
+                                options.getOptionTemplateByKey("optimistic.types").getName()));
+            }
+            _lazy_compilation = true;
+        } else {
+            _lazy_compilation = lazy_compilation;
+        }
         _loader_per_compile   = options.getBoolean("loader.per.compile");
         _no_java              = options.getBoolean("no.java");
         _no_syntax_extensions = options.getBoolean("no.syntax.extensions");
diff --git a/src/jdk/nashorn/internal/runtime/ScriptFunction.java b/src/jdk/nashorn/internal/runtime/ScriptFunction.java
index d999c11..c092230 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java
@@ -22,7 +22,6 @@
  * 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.virtualCallNoLookup;
@@ -40,6 +39,7 @@
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
+import java.util.concurrent.atomic.LongAdder;
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
@@ -55,38 +55,54 @@
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 
 /**
- * Runtime representation of a JavaScript function.
+ * Runtime representation of a JavaScript function. This class has only private
+ * and protected constructors. There are no *public* constructors - but only
+ * factory methods that follow the naming pattern "createXYZ".
  */
-public abstract class ScriptFunction extends ScriptObject {
+public class ScriptFunction extends ScriptObject {
 
-    /** Method handle for prototype getter for this ScriptFunction */
+    /**
+     * Method handle for prototype getter for this ScriptFunction
+     */
     public static final MethodHandle G$PROTOTYPE = findOwnMH_S("G$prototype", Object.class, Object.class);
 
-    /** Method handle for prototype setter for this ScriptFunction */
+    /**
+     * Method handle for prototype setter for this ScriptFunction
+     */
     public static final MethodHandle S$PROTOTYPE = findOwnMH_S("S$prototype", void.class, Object.class, Object.class);
 
-    /** Method handle for length getter for this ScriptFunction */
+    /**
+     * Method handle for length getter for this ScriptFunction
+     */
     public static final MethodHandle G$LENGTH = findOwnMH_S("G$length", int.class, Object.class);
 
-    /** Method handle for name getter for this ScriptFunction */
+    /**
+     * Method handle for name getter for this ScriptFunction
+     */
     public static final MethodHandle G$NAME = findOwnMH_S("G$name", Object.class, Object.class);
 
-    /** Method handle used for implementing sync() in mozilla_compat */
+    /**
+     * Method handle used for implementing sync() in mozilla_compat
+     */
     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 */
+    /**
+     * Method handle for allocate function for this ScriptFunction
+     */
     static final MethodHandle ALLOCATE = findOwnMH_V("allocate", Object.class);
 
     private static final MethodHandle WRAPFILTER = findOwnMH_S("wrapFilter", 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 */
+    /**
+     * 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_S("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_APPLY_FUNCTION  = findOwnMH_S("isApplyFunction", boolean.class, boolean.class, Object.class, Object.class);
+    private static final MethodHandle IS_APPLY_FUNCTION = findOwnMH_S("isApplyFunction", boolean.class, boolean.class, Object.class, Object.class);
 
     private static final MethodHandle IS_NONSTRICT_FUNCTION = findOwnMH_S("isNonStrictFunction", boolean.class, Object.class, Object.class, ScriptFunctionData.class);
 
@@ -94,56 +110,298 @@
 
     private static final MethodHandle WRAP_THIS = MH.findStatic(MethodHandles.lookup(), ScriptFunctionData.class, "wrapThis", MH.type(Object.class, Object.class));
 
-    /** The parent scope. */
+    // various property maps used for different kinds of functions
+    // property map for anonymous function that serves as Function.prototype
+    private static final PropertyMap anonmap$;
+    // property map for strict mode functions
+    private static final PropertyMap strictmodemap$;
+    // property map for bound functions
+    private static final PropertyMap boundfunctionmap$;
+    // property map for non-strict, non-bound functions.
+    private static final PropertyMap map$;
+
+    // Marker object for lazily initialized prototype object
+    private static final Object LAZY_PROTOTYPE = new Object();
+
+    private static PropertyMap createStrictModeMap(final PropertyMap map) {
+        final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
+        PropertyMap newMap = map;
+        // Need to add properties directly to map since slots are assigned speculatively by newUserAccessors.
+        newMap = newMap.addPropertyNoHistory(map.newUserAccessors("arguments", flags));
+        newMap = newMap.addPropertyNoHistory(map.newUserAccessors("caller", flags));
+        return newMap;
+    }
+
+    private static PropertyMap createBoundFunctionMap(final PropertyMap strictModeMap) {
+        // Bound function map is same as strict function map, but additionally lacks the "prototype" property, see
+        // ECMAScript 5.1 section 15.3.4.5
+        return strictModeMap.deleteProperty(strictModeMap.findProperty("prototype"));
+    }
+
+    static {
+        anonmap$ = PropertyMap.newMap();
+        final ArrayList<Property> properties = new ArrayList<>(3);
+        properties.add(AccessorProperty.create("prototype", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE, G$PROTOTYPE, S$PROTOTYPE));
+        properties.add(AccessorProperty.create("length", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$LENGTH, null));
+        properties.add(AccessorProperty.create("name", Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE, G$NAME, null));
+        map$ = PropertyMap.newMap(properties);
+        strictmodemap$ = createStrictModeMap(map$);
+        boundfunctionmap$ = createBoundFunctionMap(strictmodemap$);
+    }
+
+    private static boolean isStrict(final int flags) {
+        return (flags & ScriptFunctionData.IS_STRICT) != 0;
+    }
+
+    // Choose the map based on strict mode!
+    private static PropertyMap getMap(final boolean strict) {
+        return strict ? strictmodemap$ : map$;
+    }
+
+    /**
+     * The parent scope.
+     */
     private final ScriptObject scope;
 
     private final ScriptFunctionData data;
 
-    /** The property map used for newly allocated object when function is used as constructor. */
+    /**
+     * The property map used for newly allocated object when function is used as
+     * constructor.
+     */
     protected PropertyMap allocatorMap;
 
     /**
+     * Reference to constructor prototype.
+     */
+    protected Object prototype;
+
+    /**
      * Constructor
      *
-     * @param name          function name
-     * @param methodHandle  method handle to function (if specializations are present, assumed to be most generic)
-     * @param map           property map
-     * @param scope         scope
-     * @param specs         specialized version of this function - other method handles
-     * @param flags         {@link ScriptFunctionData} flags
+     * @param data static function data
+     * @param map property map
+     * @param scope scope
      */
-    protected ScriptFunction(
-            final String name,
-            final MethodHandle methodHandle,
+    private ScriptFunction(
+            final ScriptFunctionData data,
             final PropertyMap map,
             final ScriptObject scope,
-            final Specialization[] specs,
-            final int flags) {
+            final Global global) {
 
-        this(new FinalScriptFunctionData(name, methodHandle, specs, flags), map, scope);
+        super(map);
+
+        if (Context.DEBUG) {
+            constructorCount.increment();
+        }
+
+        this.data = data;
+        this.scope = scope;
+        this.setInitialProto(global.getFunctionPrototype());
+        this.prototype = LAZY_PROTOTYPE;
+
+        // We have to fill user accessor functions late as these are stored
+        // in this object rather than in the PropertyMap of this object.
+        assert objectSpill == null;
+        if (isStrict() || isBoundFunction()) {
+            final ScriptFunction typeErrorThrower = global.getTypeErrorThrower();
+            initUserAccessors("arguments", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower);
+            initUserAccessors("caller", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower);
+        }
     }
 
     /**
      * Constructor
      *
-     * @param data          static function data
-     * @param map           property map
-     * @param scope         scope
+     * @param name function name
+     * @param methodHandle method handle to function (if specializations are
+     * present, assumed to be most generic)
+     * @param map property map
+     * @param scope scope
+     * @param specs specialized version of this function - other method handles
+     * @param flags {@link ScriptFunctionData} flags
      */
-    protected ScriptFunction(
-            final ScriptFunctionData data,
+    private ScriptFunction(
+            final String name,
+            final MethodHandle methodHandle,
             final PropertyMap map,
-            final ScriptObject scope) {
+            final ScriptObject scope,
+            final Specialization[] specs,
+            final int flags,
+            final Global global) {
+        this(new FinalScriptFunctionData(name, methodHandle, specs, flags), map, scope, global);
+    }
 
-        super(map);
+    /**
+     * Constructor
+     *
+     * @param name name of function
+     * @param methodHandle handle for invocation
+     * @param scope scope object
+     * @param specs specialized versions of this method, if available, null
+     * otherwise
+     * @param flags {@link ScriptFunctionData} flags
+     */
+    private ScriptFunction(
+            final String name,
+            final MethodHandle methodHandle,
+            final ScriptObject scope,
+            final Specialization[] specs,
+            final int flags) {
+        this(name, methodHandle, getMap(isStrict(flags)), scope, specs, flags, Global.instance());
+    }
 
-        if (Context.DEBUG) {
-            constructorCount++;
+    /**
+     * Constructor called by Nasgen generated code, zero added members, use the
+     * default map. Creates builtin functions only.
+     *
+     * @param name name of function
+     * @param invokeHandle handle for invocation
+     * @param specs specialized versions of this method, if available, null
+     * otherwise
+     */
+    protected ScriptFunction(final String name, final MethodHandle invokeHandle, final Specialization[] specs) {
+        this(name, invokeHandle, map$, null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR, Global.instance());
+    }
+
+    /**
+     * Constructor called by Nasgen generated code, non zero member count, use
+     * the map passed as argument. Creates builtin functions only.
+     *
+     * @param name name of function
+     * @param invokeHandle handle for invocation
+     * @param map initial property map
+     * @param specs specialized versions of this method, if available, null
+     * otherwise
+     */
+    protected ScriptFunction(final String name, final MethodHandle invokeHandle, final PropertyMap map, final Specialization[] specs) {
+        this(name, invokeHandle, map.addAll(map$), null, specs, ScriptFunctionData.IS_BUILTIN_CONSTRUCTOR, Global.instance());
+    }
+
+    // Factory methods to create various functions
+    /**
+     * Factory method called by compiler generated code for functions that need
+     * parent scope.
+     *
+     * @param constants the generated class' constant array
+     * @param index the index of the {@code RecompilableScriptFunctionData}
+     * object in the constants array.
+     * @param scope the parent scope object
+     * @return a newly created function object
+     */
+    public static ScriptFunction create(final Object[] constants, final int index, final ScriptObject scope) {
+        final RecompilableScriptFunctionData data = (RecompilableScriptFunctionData) constants[index];
+        return new ScriptFunction(data, getMap(data.isStrict()), scope, Global.instance());
+    }
+
+    /**
+     * Factory method called by compiler generated code for functions that don't
+     * need parent scope.
+     *
+     * @param constants the generated class' constant array
+     * @param index the index of the {@code RecompilableScriptFunctionData}
+     * object in the constants array.
+     * @return a newly created function object
+     */
+    public static ScriptFunction create(final Object[] constants, final int index) {
+        return create(constants, index, null);
+    }
+
+    /**
+     * Create anonymous function that serves as Function.prototype
+     *
+     * @return anonymous function object
+     */
+    public static ScriptFunction createAnonymous() {
+        return new ScriptFunction("", GlobalFunctions.ANONYMOUS, anonmap$, null);
+    }
+
+    // builtin function create helper factory
+    private static ScriptFunction createBuiltin(final String name, final MethodHandle methodHandle, final Specialization[] specs, final int flags) {
+        final ScriptFunction func = new ScriptFunction(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;
+    }
+
+    /**
+     * Factory method for non-constructor built-in functions
+     *
+     * @param name function name
+     * @param methodHandle handle for invocation
+     * @param specs specialized versions of function if available, null
+     * otherwise
+     * @return new ScriptFunction
+     */
+    public static ScriptFunction createBuiltin(final String name, final MethodHandle methodHandle, final Specialization[] specs) {
+        return ScriptFunction.createBuiltin(name, methodHandle, specs, ScriptFunctionData.IS_BUILTIN);
+    }
+
+    /**
+     * Factory method for non-constructor built-in functions
+     *
+     * @param name function name
+     * @param methodHandle handle for invocation
+     * @return new ScriptFunction
+     */
+    public static ScriptFunction createBuiltin(final String name, final MethodHandle methodHandle) {
+        return ScriptFunction.createBuiltin(name, methodHandle, null);
+    }
+
+    /**
+     * Factory method for non-constructor built-in, strict functions
+     *
+     * @param name function name
+     * @param methodHandle handle for invocation
+     * @return new ScriptFunction
+     */
+    public static ScriptFunction createStrictBuiltin(final String name, final MethodHandle methodHandle) {
+        return ScriptFunction.createBuiltin(name, methodHandle, null, ScriptFunctionData.IS_BUILTIN | ScriptFunctionData.IS_STRICT);
+    }
+
+    // Subclass to represent bound functions
+    private static class Bound extends ScriptFunction {
+        private final ScriptFunction target;
+
+        Bound(final ScriptFunctionData boundData, final ScriptFunction target) {
+            super(boundData, boundfunctionmap$, null, Global.instance());
+            setPrototype(ScriptRuntime.UNDEFINED);
+            this.target = target;
         }
 
-        this.data  = data;
-        this.scope = scope;
-        this.allocatorMap = data.getAllocatorMap();
+        @Override
+        protected ScriptFunction getTargetFunction() {
+            return target;
+        }
+    }
+
+    /**
+     * Creates a version of this function bound to a specific "self" and other
+     * arguments, as per {@code Function.prototype.bind} functionality in
+     * ECMAScript 5.1 section 15.3.4.5.
+     *
+     * @param self the self to bind to this function. Can be null (in which
+     * case, null is bound as this).
+     * @param args additional arguments to bind to this function. Can be null or
+     * empty to not bind additional arguments.
+     * @return a function with the specified self and parameters bound.
+     */
+    public final ScriptFunction createBound(final Object self, final Object[] args) {
+        return new Bound(data.makeBoundFunctionData(this, self, args), getTargetFunction());
+    }
+
+    /**
+     * Create a function that invokes this function synchronized on {@code sync}
+     * or the self object of the invocation.
+     *
+     * @param sync the Object to synchronize on, or undefined
+     * @return synchronized function
+     */
+    public final ScriptFunction createSynchronized(final Object sync) {
+        final MethodHandle mh = MH.insertArguments(ScriptFunction.INVOKE_SYNC, 0, this, sync);
+        return createBuiltin(getName(), mh);
     }
 
     @Override
@@ -152,8 +410,8 @@
     }
 
     /**
-     * ECMA 15.3.5.3 [[HasInstance]] (V)
-     * Step 3 if "prototype" value is not an Object, throw TypeError
+     * ECMA 15.3.5.3 [[HasInstance]] (V) Step 3 if "prototype" value is not an
+     * Object, throw TypeError
      */
     @Override
     public boolean isInstance(final ScriptObject instance) {
@@ -172,22 +430,25 @@
     }
 
     /**
-     * Returns the target function for this function. If the function was not created using
-     * {@link #makeBoundFunction(Object, Object[])}, its target function is itself. If it is bound, its target function
-     * is the target function of the function it was made from (therefore, the target function is always the final,
-     * unbound recipient of the calls).
+     * Returns the target function for this function. If the function was not
+     * created using {@link #createBound(Object, Object[])}, its target
+     * function is itself. If it is bound, its target function is the target
+     * function of the function it was made from (therefore, the target function
+     * is always the final, unbound recipient of the calls).
+     *
      * @return the target function for this function.
      */
     protected ScriptFunction getTargetFunction() {
         return this;
     }
 
-    boolean isBoundFunction() {
+    final boolean isBoundFunction() {
         return getTargetFunction() != this;
     }
 
     /**
      * Set the arity of this ScriptFunction
+     *
      * @param arity arity
      */
     public final void setArity(final int arity) {
@@ -196,104 +457,105 @@
 
     /**
      * Is this a ECMAScript 'use strict' function?
+     *
      * @return true if function is in strict mode
      */
-    public boolean isStrict() {
+    public final boolean isStrict() {
         return data.isStrict();
     }
 
     /**
-     * Returns true if this is a non-strict, non-built-in function that requires non-primitive this argument
-     * according to ECMA 10.4.3.
+     * Returns true if this is a non-strict, non-built-in function that requires
+     * non-primitive this argument according to ECMA 10.4.3.
+     *
      * @return true if this argument must be an object
      */
-    public boolean needsWrappedThis() {
+    public final boolean needsWrappedThis() {
         return data.needsWrappedThis();
     }
 
     private static boolean needsWrappedThis(final Object fn) {
-        return fn instanceof ScriptFunction ? ((ScriptFunction)fn).needsWrappedThis() : false;
+        return fn instanceof ScriptFunction ? ((ScriptFunction) fn).needsWrappedThis() : false;
     }
 
     /**
      * Execute this script function.
-     * @param self  Target object.
-     * @param arguments  Call arguments.
+     *
+     * @param self Target object.
+     * @param arguments Call arguments.
      * @return ScriptFunction result.
-     * @throws Throwable if there is an exception/error with the invocation or thrown from it
+     * @throws Throwable if there is an exception/error with the invocation or
+     * thrown from it
      */
-    Object invoke(final Object self, final Object... arguments) throws Throwable {
+    final Object invoke(final Object self, final Object... arguments) throws Throwable {
         if (Context.DEBUG) {
-            invokes++;
+            invokes.increment();
         }
         return data.invoke(this, self, arguments);
     }
 
     /**
      * Execute this script function as a constructor.
-     * @param arguments  Call arguments.
+     *
+     * @param arguments Call arguments.
      * @return Newly constructed result.
-     * @throws Throwable if there is an exception/error with the invocation or thrown from it
+     * @throws Throwable if there is an exception/error with the invocation or
+     * thrown from it
      */
-    Object construct(final Object... arguments) throws Throwable {
+    final Object construct(final Object... arguments) throws Throwable {
         return data.construct(this, arguments);
     }
 
     /**
-     * Allocate function. Called from generated {@link ScriptObject} code
-     * for allocation as a factory method
+     * Allocate function. Called from generated {@link ScriptObject} code for
+     * allocation as a factory method
      *
-     * @return a new instance of the {@link ScriptObject} whose allocator this is
+     * @return a new instance of the {@link ScriptObject} whose allocator this
+     * is
      */
     @SuppressWarnings("unused")
     private Object allocate() {
         if (Context.DEBUG) {
-            allocations++;
+            allocations.increment();
         }
 
         assert !isBoundFunction(); // allocate never invoked on bound functions
 
-        final ScriptObject object = data.allocate(allocatorMap);
+        final ScriptObject prototype = getAllocatorPrototype();
+        final ScriptObject object = data.allocate(getAllocatorMap(prototype));
 
         if (object != null) {
-            final Object prototype = getPrototype();
-            if (prototype instanceof ScriptObject) {
-                object.setInitialProto((ScriptObject)prototype);
-            }
-
-            if (object.getProto() == null) {
-                object.setInitialProto(getObjectPrototype());
-            }
+            object.setInitialProto(prototype);
         }
 
         return object;
     }
 
     /**
-     * Return Object.prototype - used by "allocate"
-     * @return Object.prototype
+     * Get the property map used by "allocate"
+     * @param prototype actual prototype object
+     * @return property map
      */
-    protected abstract ScriptObject getObjectPrototype();
-
-    /**
-     * Creates a version of this function bound to a specific "self" and other arguments, as per
-     * {@code Function.prototype.bind} functionality in ECMAScript 5.1 section 15.3.4.5.
-     * @param self the self to bind to this function. Can be null (in which case, null is bound as this).
-     * @param args additional arguments to bind to this function. Can be null or empty to not bind additional arguments.
-     * @return a function with the specified self and parameters bound.
-     */
-    protected ScriptFunction makeBoundFunction(final Object self, final Object[] args) {
-        return makeBoundFunction(data.makeBoundFunctionData(this, self, args));
+    private synchronized PropertyMap getAllocatorMap(final ScriptObject prototype) {
+        if (allocatorMap == null || allocatorMap.isInvalidSharedMapFor(prototype)) {
+            // The prototype map has changed since this function was last used as constructor.
+            // Get a new allocator map.
+            allocatorMap = data.getAllocatorMap(prototype);
+        }
+        return allocatorMap;
     }
 
     /**
-     * Create a version of this function as in {@link ScriptFunction#makeBoundFunction(Object, Object[])},
-     * but using a {@link ScriptFunctionData} for the bound data.
-     *
-     * @param boundData ScriptFuntionData for the bound function
-     * @return a function with the bindings performed according to the given data
+     * Return the actual prototype used by "allocate"
+     * @return allocator prototype
      */
-    protected abstract ScriptFunction makeBoundFunction(ScriptFunctionData boundData);
+    private ScriptObject getAllocatorPrototype() {
+        final Object prototype = getPrototype();
+        if (prototype instanceof ScriptObject) {
+            return (ScriptObject) prototype;
+        }
+        return Global.objectPrototype();
+    }
 
     @Override
     public final String safeToString() {
@@ -301,13 +563,15 @@
     }
 
     @Override
-    public String toString() {
+    public final String toString() {
         return data.toString();
     }
 
     /**
-     * Get this function as a String containing its source code. If no source code
-     * exists in this ScriptFunction, its contents will be displayed as {@code [native code]}
+     * Get this function as a String containing its source code. If no source
+     * code exists in this ScriptFunction, its contents will be displayed as
+     * {@code [native code]}
+     *
      * @return string representation of this function's source
      */
     public final String toSource() {
@@ -316,27 +580,32 @@
 
     /**
      * Get the prototype object for this function
+     *
      * @return prototype
      */
-    public abstract Object getPrototype();
+    public final Object getPrototype() {
+        if (prototype == LAZY_PROTOTYPE) {
+            prototype = new PrototypeObject(this);
+        }
+        return prototype;
+    }
 
     /**
      * Set the prototype object for this function
-     * @param prototype new prototype object
+     *
+     * @param newPrototype new prototype object
      */
-    public abstract void setPrototype(Object prototype);
+    public synchronized final void setPrototype(final Object newPrototype) {
+        if (newPrototype instanceof ScriptObject && newPrototype != this.prototype && allocatorMap != null) {
+            // Unset allocator map to be replaced with one matching the new prototype.
+            allocatorMap = null;
+        }
+        this.prototype = newPrototype;
+    }
 
     /**
-     * Create a function that invokes this function synchronized on {@code sync} or the self object
-     * of the invocation.
-     * @param sync the Object to synchronize on, or undefined
-     * @return synchronized function
-     */
-   public abstract ScriptFunction makeSynchronizedFunction(Object sync);
-
-    /**
-     * Return the invoke handle bound to a given ScriptObject self reference.
-     * If callee parameter is required result is rebound to this.
+     * Return the invoke handle bound to a given ScriptObject self reference. If
+     * callee parameter is required result is rebound to this.
      *
      * @param self self reference
      * @return bound invoke handle
@@ -346,9 +615,12 @@
     }
 
     /**
-     * Bind the method handle to this {@code ScriptFunction} instance if it needs a callee parameter. If this function's
-     * method handles don't have a callee parameter, the handle is returned unchanged.
-     * @param methodHandle the method handle to potentially bind to this function instance.
+     * Bind the method handle to this {@code ScriptFunction} instance if it
+     * needs a callee parameter. If this function's method handles don't have a
+     * callee parameter, the handle is returned unchanged.
+     *
+     * @param methodHandle the method handle to potentially bind to this
+     * function instance.
      * @return the potentially bound method handle
      */
     private MethodHandle bindToCalleeIfNeeded(final MethodHandle methodHandle) {
@@ -358,15 +630,16 @@
 
     /**
      * Get the name for this function
+     *
      * @return the name
      */
     public final String getName() {
         return data.getName();
     }
 
-
     /**
      * Get the scope for this function
+     *
      * @return the scope
      */
     public final ScriptObject getScope() {
@@ -377,36 +650,37 @@
      * Prototype getter for this ScriptFunction - follows the naming convention
      * used by Nasgen and the code generator
      *
-     * @param self  self reference
+     * @param self self reference
      * @return self's prototype
      */
     public static Object G$prototype(final Object self) {
-        return self instanceof ScriptFunction ?
-            ((ScriptFunction)self).getPrototype() :
-            UNDEFINED;
+        return self instanceof ScriptFunction
+                ? ((ScriptFunction) self).getPrototype()
+                : UNDEFINED;
     }
 
     /**
      * Prototype setter for this ScriptFunction - follows the naming convention
      * used by Nasgen and the code generator
      *
-     * @param self  self reference
+     * @param self self reference
      * @param prototype prototype to set
      */
     public static void S$prototype(final Object self, final Object prototype) {
         if (self instanceof ScriptFunction) {
-            ((ScriptFunction)self).setPrototype(prototype);
+            ((ScriptFunction) self).setPrototype(prototype);
         }
     }
 
     /**
      * Length getter - ECMA 15.3.3.2: Function.length
+     *
      * @param self self reference
      * @return length
      */
     public static int G$length(final Object self) {
         if (self instanceof ScriptFunction) {
-            return ((ScriptFunction)self).data.getArity();
+            return ((ScriptFunction) self).data.getArity();
         }
 
         return 0;
@@ -414,12 +688,13 @@
 
     /**
      * Name getter - ECMA Function.name
+     *
      * @param self self refence
      * @return the name, or undefined if none
      */
     public static Object G$name(final Object self) {
         if (self instanceof ScriptFunction) {
-            return ((ScriptFunction)self).getName();
+            return ((ScriptFunction) self).getName();
         }
 
         return UNDEFINED;
@@ -427,6 +702,7 @@
 
     /**
      * Get the prototype for this ScriptFunction
+     *
      * @param constructor constructor
      * @return prototype, or null if given constructor is not a ScriptFunction
      */
@@ -434,7 +710,7 @@
         if (constructor != null) {
             final Object proto = constructor.getPrototype();
             if (proto instanceof ScriptObject) {
-                return (ScriptObject)proto;
+                return (ScriptObject) proto;
             }
         }
 
@@ -442,29 +718,37 @@
     }
 
     // These counters are updated only in debug mode.
-    private static int constructorCount;
-    private static int invokes;
-    private static int allocations;
+    private static LongAdder constructorCount;
+    private static LongAdder invokes;
+    private static LongAdder allocations;
+
+    static {
+        if (Context.DEBUG) {
+            constructorCount = new LongAdder();
+            invokes = new LongAdder();
+            allocations = new LongAdder();
+        }
+    }
 
     /**
      * @return the constructorCount
      */
-    public static int getConstructorCount() {
-        return constructorCount;
+    public static long getConstructorCount() {
+        return constructorCount.longValue();
     }
 
     /**
      * @return the invokes
      */
-    public static int getInvokes() {
-        return invokes;
+    public static long getInvokes() {
+        return invokes.longValue();
     }
 
     /**
      * @return the allocations
      */
-    public static int getAllocations() {
-        return allocations;
+    public static long getAllocations() {
+        return allocations.longValue();
     }
 
     @Override
@@ -484,7 +768,6 @@
         return Context.getGlobal().wrapAsObject(obj);
     }
 
-
     @SuppressWarnings("unused")
     private static Object globalFilter(final Object object) {
         // replace whatever we get with the current global object
@@ -492,14 +775,16 @@
     }
 
     /**
-     * Some receivers are primitive, in that case, according to the Spec we create a new
-     * native object per callsite with the wrap filter. We can only apply optimistic builtins
-     * if there is no per instance state saved for these wrapped objects (e.g. currently NativeStrings),
-     * otherwise we can't create optimistic versions
+     * Some receivers are primitive, in that case, according to the Spec we
+     * create a new native object per callsite with the wrap filter. We can only
+     * apply optimistic builtins if there is no per instance state saved for
+     * these wrapped objects (e.g. currently NativeStrings), otherwise we can't
+     * create optimistic versions
      *
-     * @param self            receiver
-     * @param linkLogicClass  linkLogicClass, or null if no link logic exists
-     * @return link logic instance, or null if one could not be constructed for this receiver
+     * @param self receiver
+     * @param linkLogicClass linkLogicClass, or null if no link logic exists
+     * @return link logic instance, or null if one could not be constructed for
+     * this receiver
      */
     private static LinkLogic getLinkLogic(final Object self, final Class<? extends LinkLogic> linkLogicClass) {
         if (linkLogicClass == null) {
@@ -512,25 +797,25 @@
 
         final Object wrappedSelf = wrapFilter(self);
         if (wrappedSelf instanceof OptimisticBuiltins) {
-            if (wrappedSelf != self && ((OptimisticBuiltins)wrappedSelf).hasPerInstanceAssumptions()) {
+            if (wrappedSelf != self && ((OptimisticBuiltins) wrappedSelf).hasPerInstanceAssumptions()) {
                 return null; //pessimistic - we created a wrapped object different from the primitive, but the assumptions have instance state
             }
-            return ((OptimisticBuiltins)wrappedSelf).getLinkLogic(linkLogicClass);
+            return ((OptimisticBuiltins) wrappedSelf).getLinkLogic(linkLogicClass);
         }
         return null;
     }
 
     /**
-     * dyn:call call site signature: (callee, thiz, [args...])
-     * generated method signature:   (callee, thiz, [args...])
+     * dyn:call call site signature: (callee, thiz, [args...]) generated method
+     * signature: (callee, thiz, [args...])
      *
      * cases:
      * (a) method has callee parameter
-     *   (1) for local/scope calls, we just bind thiz and drop the second argument.
-     *   (2) for normal this-calls, we have to swap thiz and callee to get matching signatures.
+     *     (1) for local/scope calls, we just bind thiz and drop the second argument.
+     *     (2) for normal this-calls, we have to swap thiz and callee to get matching signatures.
      * (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.
+     *     (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
      */
@@ -538,11 +823,11 @@
     protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) {
         final MethodType type = desc.getMethodType();
 
-        final String  name       = getName();
+        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 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;
 
@@ -563,7 +848,7 @@
             return new GuardedInvocation(
                     handle,
                     null,
-                    (SwitchPoint)null,
+                    (SwitchPoint) null,
                     ClassCastException.class);
         }
 
@@ -652,6 +937,13 @@
             }
         }
 
+        // Is this an unstable callsite which was earlier apply-to-call optimized?
+        // If so, earlier apply2call would have exploded arguments. We have to convert
+        // that as an array again!
+        if (isUnstable && NashornCallSiteDescriptor.isApplyToCall(desc)) {
+            boundHandle = MH.asCollector(boundHandle, Object[].class, type.parameterCount() - 2);
+        }
+
         boundHandle = pairArguments(boundHandle, type);
 
         if (bestInvoker.getSwitchPoints() != null) {
@@ -666,14 +958,14 @@
                                 this,
                                 cf.getFlags()) :
                         guard,
-                        spsArray,
+                spsArray,
                 exceptionGuard);
     }
 
     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()) {
+        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.
@@ -780,7 +1072,7 @@
                 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);
+                inv = MH.insertArguments(inv, 2, (Object) ScriptRuntime.EMPTY_ARRAY);
             }
         }
 
@@ -845,7 +1137,7 @@
             final LinkRequest request, final Object[] args) {
         final MethodType descType = desc.getMethodType();
         final int paramCount = descType.parameterCount();
-        final Object[] varArgs = (Object[])args[paramCount - 1];
+        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;
@@ -887,7 +1179,7 @@
         // 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()) {
+        if (guardType.parameterType(guardParamCount - 1).isArray()) {
             arrayConvertingGuard = MH.filterArguments(guard, guardParamCount - 1, NativeFunction.TO_APPLY_ARGS);
         } else {
             arrayConvertingGuard = guard;
@@ -897,19 +1189,20 @@
     }
 
     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);
-     }
+        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.
      *
-     * These don't want a callee parameter, so bind that. Name binding is optional.
+     * 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(data.getGenericInvoker(scope)), bindName), type);
@@ -933,10 +1226,11 @@
     }
 
     /**
-     * Get the guard that checks if a {@link ScriptFunction} is equal to
-     * a known ScriptFunction, using reference comparison
+     * Get the guard that checks if a {@link ScriptFunction} is equal to a known
+     * ScriptFunction, using reference comparison
      *
-     * @param function The ScriptFunction to check against. This will be bound to the guard method handle
+     * @param function The ScriptFunction to check against. This will be bound
+     * to the guard method handle
      *
      * @return method handle for guard
      */
@@ -951,11 +1245,12 @@
     }
 
     /**
-     * Get a guard that checks if a {@link ScriptFunction} is equal to
-     * a known ScriptFunction using reference comparison, and whether the type of
-     * the second argument (this-object) is not a JavaScript primitive type.
+     * Get a guard that checks if a {@link ScriptFunction} is equal to a known
+     * ScriptFunction using reference comparison, and whether the type of the
+     * second argument (this-object) is not a JavaScript primitive type.
      *
-     * @param function The ScriptFunction to check against. This will be bound to the guard method handle
+     * @param function The ScriptFunction to check against. This will be bound
+     * to the guard method handle
      *
      * @return method handle for guard
      */
@@ -966,12 +1261,12 @@
 
     @SuppressWarnings("unused")
     private static boolean isFunctionMH(final Object self, final ScriptFunctionData data) {
-        return self instanceof ScriptFunction && ((ScriptFunction)self).data == data;
+        return self instanceof ScriptFunction && ((ScriptFunction) self).data == data;
     }
 
     @SuppressWarnings("unused")
     private static boolean isNonStrictFunction(final Object self, final Object arg, final ScriptFunctionData data) {
-        return self instanceof ScriptFunction && ((ScriptFunction)self).data == data && arg instanceof ScriptObject;
+        return self instanceof ScriptFunction && ((ScriptFunction) self).data == data && arg instanceof ScriptObject;
     }
 
     //TODO this can probably be removed given that we have builtin switchpoints in the context
@@ -984,7 +1279,7 @@
     @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;
@@ -1008,4 +1303,3 @@
         return MH.findVirtual(MethodHandles.lookup(), ScriptFunction.class, name, MH.type(rtype, types));
     }
 }
-
diff --git a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java
index 3472cda..683c7ab 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java
@@ -28,6 +28,7 @@
 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 java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.Serializable;
@@ -79,24 +80,24 @@
     private static final MethodHandle BIND_VAR_ARGS = findOwnMH("bindVarArgs", Object[].class, Object[].class, Object[].class);
 
     /** Is this a strict mode function? */
-    public static final int IS_STRICT      = 1 << 0;
+    public static final int IS_STRICT            = 1 << 0;
     /** Is this a built-in function? */
-    public static final int IS_BUILTIN     = 1 << 1;
+    public static final int IS_BUILTIN           = 1 << 1;
     /** Is this a constructor function? */
-    public static final int IS_CONSTRUCTOR = 1 << 2;
+    public static final int IS_CONSTRUCTOR       = 1 << 2;
     /** Does this function expect a callee argument? */
-    public static final int NEEDS_CALLEE   = 1 << 3;
+    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;
+    public static final int USES_THIS            = 1 << 4;
     /** Is this a variable arity function? */
-    public static final int IS_VARIABLE_ARITY = 1 << 5;
+    public static final int IS_VARIABLE_ARITY    = 1 << 5;
+    /** Is this a object literal property getter or setter? */
+    public static final int IS_PROPERTY_ACCESSOR = 1 << 6;
 
     /** Flag for strict or built-in functions */
     public static final int IS_STRICT_OR_BUILTIN = IS_STRICT | IS_BUILTIN;
     /** Flag for built-in constructors */
     public static final int IS_BUILTIN_CONSTRUCTOR = IS_BUILTIN | IS_CONSTRUCTOR;
-    /** Flag for strict constructors */
-    public static final int IS_STRICT_CONSTRUCTOR = IS_STRICT | IS_CONSTRUCTOR;
 
     private static final long serialVersionUID = 4252901245508769114L;
 
@@ -121,6 +122,10 @@
         return (flags & IS_VARIABLE_ARITY) != 0;
     }
 
+    final boolean isPropertyAccessor() {
+        return (flags & IS_PROPERTY_ACCESSOR) != 0;
+    }
+
     /**
      * Used from e.g. Native*$Constructors as an explicit call. TODO - make arity immutable and final
      * @param arity new arity
@@ -146,7 +151,7 @@
      * Is this a ScriptFunction generated with strict semantics?
      * @return true if strict, false otherwise
      */
-    public boolean isStrict() {
+    public final boolean isStrict() {
         return (flags & IS_STRICT) != 0;
     }
 
@@ -159,11 +164,11 @@
         return getName();
     }
 
-    boolean isBuiltin() {
+    final boolean isBuiltin() {
         return (flags & IS_BUILTIN) != 0;
     }
 
-    boolean isConstructor() {
+    final boolean isConstructor() {
         return (flags & IS_CONSTRUCTOR) != 0;
     }
 
@@ -174,7 +179,7 @@
      * according to ECMA 10.4.3.
      * @return true if this argument must be an object
      */
-    boolean needsWrappedThis() {
+    final boolean needsWrappedThis() {
         return (flags & USES_THIS) != 0 && (flags & IS_STRICT_OR_BUILTIN) == 0;
     }
 
@@ -313,7 +318,7 @@
      * 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
+     * a function that, when padded with undefined values, behaves differently
      * @param type actual call site type
      * @return apply to call that perfectly fits this callsite or null if none found
      */
@@ -352,35 +357,31 @@
      * @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.
+     * @param linkLogicOkay is a CompiledFunction with a LinkLogic acceptable?
      * @return the best function for the specified call site type.
      */
-    CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) {
-        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
+    abstract CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden, final boolean linkLogicOkay);
 
-        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 (!forbidden.contains(candidate) && candidate.betterThanFinal(best, callSiteType)) {
-                best = candidate;
-            }
-        }
-
-        return best;
+    /**
+     * 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.
+     */
+    final CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) {
+        return getBest(callSiteType, runtimeScope, forbidden, true);
     }
 
-
-    abstract boolean isRecompilable();
+    boolean isValidCallSite(final MethodType callSiteType) {
+        return callSiteType.parameterCount() >= 2  && // Must have at least (callee, this)
+               callSiteType.parameterType(0).isAssignableFrom(ScriptFunction.class); // Callee must be assignable from script function
+    }
 
     CompiledFunction getGeneric(final ScriptObject runtimeScope) {
-        return getBest(getGenericType(), runtimeScope, CompiledFunction.NO_FUNCTIONS);
+        return getBest(getGenericType(), runtimeScope, CompiledFunction.NO_FUNCTIONS, false);
     }
 
     /**
@@ -402,15 +403,16 @@
     /**
      * Get the property map to use for objects allocated by this function.
      *
+     * @param prototype the prototype of the allocated object
      * @return the property map for allocated objects.
      */
-    PropertyMap getAllocatorMap() {
+    PropertyMap getAllocatorMap(final ScriptObject prototype) {
         return null;
     }
 
     /**
      * This method is used to create the immutable portion of a bound function.
-     * See {@link ScriptFunction#makeBoundFunction(Object, Object[])}
+     * See {@link ScriptFunction#createBound(Object, Object[])}
      *
      * @param fn the original function being bound
      * @param self this reference to bind. Can be null.
@@ -456,8 +458,7 @@
     }
 
     static boolean isPrimitiveThis(final Object obj) {
-        return obj instanceof String || obj instanceof ConsString ||
-               obj instanceof Number || obj instanceof Boolean;
+        return JSType.isString(obj) || obj instanceof Number || obj instanceof Boolean;
     }
 
     /**
diff --git a/src/jdk/nashorn/internal/runtime/ScriptLoader.java b/src/jdk/nashorn/internal/runtime/ScriptLoader.java
index b2a54be..3b66c99 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptLoader.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptLoader.java
@@ -26,6 +26,7 @@
 package jdk.nashorn.internal.runtime;
 
 import java.security.CodeSource;
+import java.util.Objects;
 
 /**
  * Responsible for loading script generated classes.
@@ -69,8 +70,6 @@
      * @return Installed class.
      */
     synchronized Class<?> installClass(final String name, final byte[] data, final CodeSource cs) {
-        // null check
-        cs.getClass();
-        return defineClass(name, data, 0, data.length, cs);
+        return defineClass(name, data, 0, data.length, Objects.requireNonNull(cs));
     }
 }
diff --git a/src/jdk/nashorn/internal/runtime/ScriptObject.java b/src/jdk/nashorn/internal/runtime/ScriptObject.java
index c3eca18..0353bdc 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptObject.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java
@@ -28,7 +28,6 @@
 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;
@@ -65,6 +64,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.atomic.LongAdder;
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
@@ -110,20 +110,17 @@
     /** Search fall back routine name for "no such property" */
     public static final String NO_SUCH_PROPERTY_NAME = "__noSuchProperty__";
 
-    /** Per ScriptObject flag - is this a scope object? */
-    public static final int IS_SCOPE       = 1 << 0;
-
     /** Per ScriptObject flag - is this an array object? */
-    public static final int IS_ARRAY       = 1 << 1;
+    public static final int IS_ARRAY               = 1 << 0;
 
     /** Per ScriptObject flag - is this an arguments object? */
-    public static final int IS_ARGUMENTS   = 1 << 2;
+    public static final int IS_ARGUMENTS           = 1 << 1;
 
     /** Is length property not-writable? */
-    public static final int IS_LENGTH_NOT_WRITABLE = 1 << 3;
+    public static final int IS_LENGTH_NOT_WRITABLE = 1 << 2;
 
     /** Is this a builtin object? */
-    public static final int IS_BUILTIN = 1 << 4;
+    public static final int IS_BUILTIN             = 1 << 3;
 
     /**
      * Spill growth rate - by how many elements does {@link ScriptObject#primitiveSpill} and
@@ -146,19 +143,13 @@
     /** 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 retrieve prototype of this object */
     public static final MethodHandle GETPROTO      = findOwnMH_V("getProto", ScriptObject.class);
 
-    static final MethodHandle MEGAMORPHIC_GET    = findOwnMH_V("megamorphicGet", Object.class, String.class, boolean.class);
+    static final MethodHandle MEGAMORPHIC_GET    = findOwnMH_V("megamorphicGet", Object.class, String.class, boolean.class, boolean.class);
     static final MethodHandle GLOBALFILTER       = findOwnMH_S("globalFilter", Object.class, Object.class);
     static final MethodHandle DECLARE_AND_SET    = findOwnMH_V("declareAndSet", void.class, String.class, Object.class);
 
@@ -171,12 +162,6 @@
     /** 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);
 
@@ -227,7 +212,7 @@
     */
     public ScriptObject(final PropertyMap map) {
         if (Context.DEBUG) {
-            ScriptObject.count++;
+            ScriptObject.count.increment();
         }
         this.arrayData = ArrayData.EMPTY_ARRAY;
         this.setMap(map == null ? PropertyMap.newMap() : map);
@@ -240,7 +225,7 @@
      * same combination of prototype and property map.
      *
      * @param proto the prototype object
-     * @param map intial {@link PropertyMap}
+     * @param map initial {@link PropertyMap}
      */
     protected ScriptObject(final ScriptObject proto, final PropertyMap map) {
         this(map);
@@ -259,8 +244,7 @@
         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);
+        assert primitiveSpill == null || primitiveSpill.length == objectSpill.length : " primitive spill pool size is not the same length as object spill pool size";
     }
 
     /**
@@ -304,9 +288,10 @@
      */
     public void addBoundProperties(final ScriptObject source, final Property[] properties) {
         PropertyMap newMap = this.getMap();
+        final boolean extensible = newMap.isExtensible();
 
         for (final Property property : properties) {
-            newMap = addBoundProperty(newMap, source, property);
+            newMap = addBoundProperty(newMap, source, property, extensible);
         }
 
         this.setMap(newMap);
@@ -319,13 +304,18 @@
      * @param propMap the property map
      * @param source the source object
      * @param property the property to be added
+     * @param extensible whether the current object is extensible or not
      * @return the new property map
      */
-    protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final Property property) {
+    protected PropertyMap addBoundProperty(final PropertyMap propMap, final ScriptObject source, final Property property, final boolean extensible) {
         PropertyMap newMap = propMap;
         final String key = property.getKey();
         final Property oldProp = newMap.findProperty(key);
         if (oldProp == null) {
+            if (! extensible) {
+                throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this));
+            }
+
             if (property instanceof UserAccessorProperty) {
                 // Note: we copy accessor functions to this object which is semantically different from binding.
                 final UserAccessorProperty prop = this.newUserAccessors(key, property.getFlags(), property.getGetterFunction(source), property.getSetterFunction(source));
@@ -354,11 +344,15 @@
      */
     public void addBoundProperties(final Object source, final AccessorProperty[] properties) {
         PropertyMap newMap = this.getMap();
+        final boolean extensible = newMap.isExtensible();
 
         for (final AccessorProperty property : properties) {
             final String key = property.getKey();
 
             if (newMap.findProperty(key) == null) {
+                if (! extensible) {
+                    throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this));
+                }
                 newMap = newMap.addPropertyBind(property, source);
             }
         }
@@ -410,14 +404,6 @@
     }
 
     /**
-     * ECMA 8.10.3 IsGenericDescriptor ( Desc )
-     * @return true if this has a descriptor describing an {@link AccessorPropertyDescriptor} or {@link DataPropertyDescriptor}
-     */
-    public final boolean isGenericDescriptor() {
-        return isAccessorDescriptor() || isDataDescriptor();
-    }
-
-    /**
       * ECMA 8.10.5 ToPropertyDescriptor ( Obj )
       *
       * @return property descriptor
@@ -722,8 +708,11 @@
     public void defineOwnProperty(final int index, final Object value) {
         assert isValidArrayIndex(index) : "invalid array index";
         final long longIndex = ArrayIndex.toLongIndex(index);
-        doesNotHaveEnsureDelete(longIndex, getArray().length(), false);
-        setArray(getArray().ensure(longIndex).set(index,value, false));
+        final long oldLength = getArray().length();
+        if (longIndex >= oldLength) {
+            setArray(getArray().ensure(longIndex).safeDelete(oldLength, longIndex - 1, false));
+        }
+        setArray(getArray().set(index, value, false));
     }
 
     private void checkIntegerKey(final String key) {
@@ -808,7 +797,7 @@
      *
      * @return FindPropertyData or null if not found.
      */
-    FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) {
+    protected FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) {
 
         final PropertyMap selfMap  = getMap();
         final Property    property = selfMap.findProperty(key);
@@ -819,9 +808,11 @@
 
         if (deep) {
             final ScriptObject myProto = getProto();
-            if (myProto != null) {
-                return myProto.findProperty(key, deep, start);
-            }
+            final FindProperty find = myProto == null ? null : myProto.findProperty(key, true, start);
+            // checkSharedProtoMap must be invoked after myProto.checkSharedProtoMap to propagate
+            // shared proto invalidation up the prototype chain. It also must be invoked when prototype is null.
+            checkSharedProtoMap();
+            return find;
         }
 
         return null;
@@ -842,7 +833,7 @@
         if (deep) {
             final ScriptObject myProto = getProto();
             if (myProto != null) {
-                return myProto.hasProperty(key, deep);
+                return myProto.hasProperty(key, true);
             }
         }
 
@@ -972,10 +963,10 @@
      * @param setter        setter for {@link UserAccessorProperty}, null if not present or N/A
      */
     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();
+        final int slot = oldMap.getFreeSpillSlot();
+        ensureSpillSize(slot);
+        objectSpill[slot] = new UserAccessorProperty.Accessors(getter, setter);
         Property    newProperty;
         PropertyMap newMap;
         do {
@@ -1002,19 +993,12 @@
             final int slot = uc.getSlot();
 
             assert uc.getLocalType() == 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;
-                    }
-                }
+            final UserAccessorProperty.Accessors gs = uc.getAccessors(this); //this crashes
+            assert gs != null;
+            //reuse existing getter setter for speed
+            gs.set(getter, setter);
+            if (uc.getFlags() == propertyFlags) {
+                return oldProperty;
             }
             newProperty = new UserAccessorProperty(uc.getKey(), propertyFlags, slot);
         } else {
@@ -1275,11 +1259,8 @@
         if (oldProto != newProto) {
             proto = newProto;
 
-            // Let current listeners know that the protototype has changed and set our map
-            final PropertyListeners listeners = getMap().getListeners();
-            if (listeners != null) {
-                listeners.protoChanged();
-            }
+            // Let current listeners know that the prototype has changed
+            getMap().protoChanged(true);
             // Replace our current allocator map with one that is associated with the new prototype.
             setMap(getMap().changeProto(newProto));
         }
@@ -1331,7 +1312,7 @@
                 }
                 p = p.getProto();
             }
-            setProto((ScriptObject)newProto);
+            setProto((ScriptObject) newProto);
         } else {
             throw typeError("cant.set.proto.to.non.object", ScriptRuntime.safeToString(this), ScriptRuntime.safeToString(newProto));
         }
@@ -1470,7 +1451,7 @@
      * in {@link ScriptFunction} for hasInstance implementation, walks
      * the proto chain
      *
-     * @param instance instace to check
+     * @param instance instance to check
      * @return true if 'instance' is an instance of this object
      */
     public boolean isInstance(final ScriptObject instance) {
@@ -1647,23 +1628,12 @@
         return getMap().isFrozen();
     }
 
-
-    /**
-     * Flag this ScriptObject as scope
-     */
-    public final void setIsScope() {
-        if (Context.DEBUG) {
-            scopeCount++;
-        }
-        flags |= IS_SCOPE;
-    }
-
     /**
      * Check whether this ScriptObject is scope
      * @return true if scope
      */
-    public final boolean isScope() {
-        return (flags & IS_SCOPE) != 0;
+    public boolean isScope() {
+        return false;
     }
 
     /**
@@ -1888,7 +1858,7 @@
      * @return GuardedInvocation to be invoked at call site.
      */
     protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc, final LinkRequest request) {
-        return notAFunction();
+        return notAFunction(desc);
     }
 
     /**
@@ -1898,14 +1868,14 @@
      * @param desc    the call site descriptor.
      * @param request the link request
      *
-     * @return GuardedInvocation to be invoed at call site.
+     * @return GuardedInvocation to be invoked at call site.
      */
     protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) {
-        return notAFunction();
+        return notAFunction(desc);
     }
 
-    private GuardedInvocation notAFunction() {
-        throw typeError("not.a.function", ScriptRuntime.safeToString(this));
+    private GuardedInvocation notAFunction(final CallSiteDescriptor desc) {
+        throw typeError("not.a.function", NashornCallSiteDescriptor.getFunctionErrorMessage(desc, this));
     }
 
     /**
@@ -1938,14 +1908,7 @@
      * Test whether this object contains in its prototype chain or is itself a with-object.
      * @return true if a with-object was found
      */
-    final boolean hasWithScope() {
-        if (isScope()) {
-            for (ScriptObject obj = this; obj != null; obj = obj.getProto()) {
-                if (obj instanceof WithObject) {
-                    return true;
-                }
-            }
-        }
+    boolean hasWithScope() {
         return false;
     }
 
@@ -2032,11 +1995,11 @@
         final ScriptObject owner = find.getOwner();
         final Class<ClassCastException> exception = explicitInstanceOfCheck ? null : ClassCastException.class;
 
-        final SwitchPoint protoSwitchPoint;
+        final SwitchPoint[] protoSwitchPoints;
 
         if (mh == null) {
             mh = Lookup.emptyGetter(returnType);
-            protoSwitchPoint = getProtoSwitchPoint(name, owner);
+            protoSwitchPoints = getProtoSwitchPoints(name, owner);
         } else if (!find.isSelf()) {
             assert mh.type().returnType().equals(returnType) :
                     "return type mismatch for getter " + mh.type().returnType() + " != " + returnType;
@@ -2044,32 +2007,30 @@
                 // Add a filter that replaces the self object with the prototype owning the property.
                 mh = addProtoFilter(mh, find.getProtoChainLength());
             }
-            protoSwitchPoint = getProtoSwitchPoint(name, owner);
+            protoSwitchPoints = getProtoSwitchPoints(name, owner);
         } else {
-            protoSwitchPoint = null;
+            protoSwitchPoints = null;
         }
 
-        assert OBJECT_FIELDS_ONLY || guard != null : "we always need a map guard here";
-
-        final GuardedInvocation inv = new GuardedInvocation(mh, guard, protoSwitchPoint, exception);
+        final GuardedInvocation inv = new GuardedInvocation(mh, guard, protoSwitchPoints, exception);
         return inv.addSwitchPoint(findBuiltinSwitchPoint(name));
     }
 
     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 invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod, NashornCallSiteDescriptor.isScope(desc));
         final MethodHandle guard   = getScriptObjectGuard(desc.getMethodType(), true);
         return new GuardedInvocation(invoker, guard);
     }
 
     @SuppressWarnings("unused")
-    private Object megamorphicGet(final String key, final boolean isMethod) {
+    private Object megamorphicGet(final String key, final boolean isMethod, final boolean isScope) {
         final FindProperty find = findProperty(key, true);
         if (find != null) {
             return find.getObjectValue();
         }
 
-        return isMethod ? getNoSuchMethod(key, INVALID_PROGRAM_POINT) : invokeNoSuchProperty(key, INVALID_PROGRAM_POINT);
+        return isMethod ? getNoSuchMethod(key, isScope, INVALID_PROGRAM_POINT) : invokeNoSuchProperty(key, isScope, INVALID_PROGRAM_POINT);
     }
 
     // Marks a property as declared and sets its value. Used as slow path for block-scoped LET and CONST
@@ -2150,17 +2111,32 @@
      * @param owner the property owner, null if property is not defined
      * @return a SwitchPoint or null
      */
-    public final SwitchPoint getProtoSwitchPoint(final String name, final ScriptObject owner) {
+    public final SwitchPoint[] getProtoSwitchPoints(final String name, final ScriptObject owner) {
         if (owner == this || getProto() == null) {
             return null;
         }
 
+        final List<SwitchPoint> switchPoints = new ArrayList<>();
         for (ScriptObject obj = this; obj != owner && obj.getProto() != null; obj = obj.getProto()) {
             final ScriptObject parent = obj.getProto();
             parent.getMap().addListener(name, obj.getMap());
+            final SwitchPoint sp = parent.getMap().getSharedProtoSwitchPoint();
+            if (sp != null && !sp.hasBeenInvalidated()) {
+                switchPoints.add(sp);
+            }
         }
 
-        return getMap().getSwitchPoint(name);
+        switchPoints.add(getMap().getSwitchPoint(name));
+        return switchPoints.toArray(new SwitchPoint[switchPoints.size()]);
+    }
+
+    private void checkSharedProtoMap() {
+        // Check if our map has an expected shared prototype property map. If it has, make sure that
+        // the prototype map has not been invalidated, and that it does match the actual map of the prototype.
+        if (getMap().isInvalidSharedMapFor(getProto())) {
+            // Change our own map to one that does not assume a shared prototype map.
+            setMap(getMap().makeUnsharedCopy());
+        }
     }
 
     /**
@@ -2242,7 +2218,7 @@
         return new GuardedInvocation(
                 Lookup.EMPTY_SETTER,
                 NashornGuards.getMapGuard(getMap(), explicitInstanceOfCheck),
-                getProtoSwitchPoint(name, null),
+                getProtoSwitchPoints(name, null),
                 explicitInstanceOfCheck ? null : ClassCastException.class);
     }
 
@@ -2339,7 +2315,7 @@
                 MH.dropArguments(
                         MH.constant(
                                 ScriptFunction.class,
-                                func.makeBoundFunction(thiz, new Object[] { name })),
+                                func.createBound(thiz, new Object[] { name })),
                         0,
                         Object.class),
                 NashornGuards.combineGuards(
@@ -2388,7 +2364,7 @@
                                 find.getGetter(Object.class, INVALID_PROGRAM_POINT, request),
                                 find.getProtoChainLength(),
                                 func),
-                        getProtoSwitchPoint(NO_SUCH_PROPERTY_NAME, find.getOwner()),
+                        getProtoSwitchPoints(NO_SUCH_PROPERTY_NAME, find.getOwner()),
                         //TODO this doesn't need a ClassCastException as guard always checks script object
                         null);
             }
@@ -2404,20 +2380,21 @@
     /**
      * Invoke fall back if a property is not found.
      * @param name Name of property.
+     * @param isScope is this a scope access?
      * @param programPoint program point
      * @return Result from call.
      */
-    protected Object invokeNoSuchProperty(final String name, final int programPoint) {
+    protected Object invokeNoSuchProperty(final String name, final boolean isScope, final int programPoint) {
         final FindProperty find = findProperty(NO_SUCH_PROPERTY_NAME, true);
+        final Object func = (find != null)? find.getObjectValue() : null;
 
         Object ret = UNDEFINED;
-
-        if (find != null) {
-            final Object func = find.getObjectValue();
-
-            if (func instanceof ScriptFunction) {
-                ret = ScriptRuntime.apply((ScriptFunction)func, this, name);
-            }
+        if (func instanceof ScriptFunction) {
+            final ScriptFunction sfunc = (ScriptFunction)func;
+            final Object self = isScope && sfunc.isStrict()? UNDEFINED : this;
+            ret = ScriptRuntime.apply(sfunc, self, name);
+        } else if (isScope) {
+            throw referenceError("not.defined", name);
         }
 
         if (isValid(programPoint)) {
@@ -2431,21 +2408,27 @@
     /**
      * Get __noSuchMethod__ as a function bound to this object and {@code name} if it is defined.
      * @param name the method name
+     * @param isScope is this a scope access?
      * @return the bound function, or undefined
      */
-    private Object getNoSuchMethod(final String name, final int programPoint) {
+    private Object getNoSuchMethod(final String name, final boolean isScope, final int programPoint) {
         final FindProperty find = findProperty(NO_SUCH_METHOD_NAME, true);
 
         if (find == null) {
-            return invokeNoSuchProperty(name, programPoint);
+            return invokeNoSuchProperty(name, isScope, programPoint);
         }
 
         final Object value = find.getObjectValue();
         if (!(value instanceof ScriptFunction)) {
+            if (isScope) {
+                throw referenceError("not.defined", name);
+            }
             return UNDEFINED;
         }
 
-        return ((ScriptFunction)value).makeBoundFunction(this, new Object[] {name});
+        final ScriptFunction func = (ScriptFunction)value;
+        final Object self = isScope && func.isStrict()? UNDEFINED : this;
+        return func.createBound(self, new Object[] {name});
     }
 
     private GuardedInvocation createEmptyGetter(final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck, final String name) {
@@ -2454,7 +2437,7 @@
         }
 
         return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()),
-                NashornGuards.getMapGuard(getMap(), explicitInstanceOfCheck), getProtoSwitchPoint(name, null),
+                NashornGuards.getMapGuard(getMap(), explicitInstanceOfCheck), getProtoSwitchPoints(name, null),
                 explicitInstanceOfCheck ? null : ClassCastException.class);
     }
 
@@ -2527,13 +2510,14 @@
 
     /**
      * Add a spill property for the given key.
-     * @param key           Property key.
-     * @param propertyFlags Property flags.
+     * @param key    Property key.
+     * @param flags  Property flags.
      * @return Added property.
      */
-    private Property addSpillProperty(final String key, final int propertyFlags, final Object value, final boolean hasInitialValue) {
+    private Property addSpillProperty(final String key, final int flags, final Object value, final boolean hasInitialValue) {
         final PropertyMap propertyMap = getMap();
         final int fieldSlot  = propertyMap.getFreeFieldSlot();
+        final int propertyFlags = flags | (useDualFields() ? Property.DUAL_FIELDS : 0);
 
         Property property;
         if (fieldSlot > -1) {
@@ -2558,7 +2542,7 @@
      * @return Setter method handle.
      */
     MethodHandle addSpill(final Class<?> type, final String key) {
-        return addSpillProperty(key, 0, null, false).getSetter(OBJECT_FIELDS_ONLY ? Object.class : type, getMap());
+        return addSpillProperty(key, 0, null, false).getSetter(type, getMap());
     }
 
     /**
@@ -2600,7 +2584,7 @@
         final int callCount      = callType.parameterCount();
 
         final boolean isCalleeVarArg = parameterCount > 0 && methodType.parameterType(parameterCount - 1).isArray();
-        final boolean isCallerVarArg = callerVarArg != null ? callerVarArg.booleanValue() : callCount > 0 &&
+        final boolean isCallerVarArg = callerVarArg != null ? callerVarArg : callCount > 0 &&
                 callType.parameterType(callCount - 1).isArray();
 
         if (isCalleeVarArg) {
@@ -2645,9 +2629,9 @@
         final int spreadArgs = mh.type().parameterCount() - callSiteParamCount + 1;
         return MH.filterArguments(
             MH.asSpreader(
-            mh,
-            Object[].class,
-            spreadArgs),
+                mh,
+                Object[].class,
+                spreadArgs),
             callSiteParamCount - 1,
             MH.insertArguments(
                 TRUNCATINGFILTER,
@@ -2693,11 +2677,7 @@
         }
 
         if (newLength > arrayLength) {
-            data = data.ensure(newLength - 1);
-            if (data.canDelete(arrayLength, newLength - 1, false)) {
-               data = data.delete(arrayLength, newLength - 1);
-            }
-            setArray(data);
+            setArray(data.ensure(newLength - 1).safeDelete(arrayLength, newLength - 1, false));
             return;
         }
 
@@ -2759,7 +2739,7 @@
             }
         }
 
-        return JSType.toInt32(invokeNoSuchProperty(key, programPoint));
+        return JSType.toInt32(invokeNoSuchProperty(key, false, programPoint));
     }
 
     @Override
@@ -2841,7 +2821,7 @@
             }
         }
 
-        return JSType.toLong(invokeNoSuchProperty(key, programPoint));
+        return JSType.toLong(invokeNoSuchProperty(key, false, programPoint));
     }
 
     @Override
@@ -2923,7 +2903,7 @@
             }
         }
 
-        return JSType.toNumber(invokeNoSuchProperty(key, INVALID_PROGRAM_POINT));
+        return JSType.toNumber(invokeNoSuchProperty(key, false, INVALID_PROGRAM_POINT));
     }
 
     @Override
@@ -3004,7 +2984,7 @@
             }
         }
 
-        return invokeNoSuchProperty(key, INVALID_PROGRAM_POINT);
+        return invokeNoSuchProperty(key, false, INVALID_PROGRAM_POINT);
     }
 
     @Override
@@ -3118,23 +3098,12 @@
         return false;
     }
 
-    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);
-            }
-            setArray(array);
-        }
-    }
-
     private void doesNotHave(final int index, final int value, final int callSiteFlags) {
         final long oldLength = getArray().length();
         final long longIndex = ArrayIndex.toLongIndex(index);
         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
             final boolean strict = isStrictFlag(callSiteFlags);
-            setArray(getArray().set(index, value, strict));
-            doesNotHaveEnsureDelete(longIndex, oldLength, strict);
+            setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
         }
     }
 
@@ -3143,8 +3112,7 @@
         final long longIndex = ArrayIndex.toLongIndex(index);
         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
             final boolean strict = isStrictFlag(callSiteFlags);
-            setArray(getArray().set(index, value, strict));
-            doesNotHaveEnsureDelete(longIndex, oldLength, strict);
+            setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
         }
     }
 
@@ -3153,8 +3121,7 @@
         final long longIndex = ArrayIndex.toLongIndex(index);
         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
             final boolean strict = isStrictFlag(callSiteFlags);
-            setArray(getArray().set(index, value, strict));
-            doesNotHaveEnsureDelete(longIndex, oldLength, strict);
+            setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
         }
     }
 
@@ -3163,8 +3130,7 @@
         final long longIndex = ArrayIndex.toLongIndex(index);
         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
             final boolean strict = isStrictFlag(callSiteFlags);
-            setArray(getArray().set(index, value, strict));
-            doesNotHaveEnsureDelete(longIndex, oldLength, strict);
+            setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
         }
     }
 
@@ -3735,24 +3701,32 @@
         return uc;
     }
 
+    /**
+     * Returns {@code true} if properties for this object should use dual field mode, {@code false} otherwise.
+     * @return {@code true} if dual fields should be used.
+     */
+    protected boolean useDualFields() {
+        return !StructureLoader.isSingleFieldStructure(getClass().getName());
+    }
+
     Object ensureSpillSize(final int slot) {
-        if (slot < spillLength) {
+        final int oldLength = objectSpill == null ? 0 : objectSpill.length;
+        if (slot < oldLength) {
             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];
+        final long[]   newPrimitiveSpill = useDualFields() ? new long[newLength] : null;
 
         if (objectSpill != null) {
-            System.arraycopy(objectSpill, 0, newObjectSpill, 0, spillLength);
-            if (!OBJECT_FIELDS_ONLY) {
-                System.arraycopy(primitiveSpill, 0, newPrimitiveSpill, 0, spillLength);
+            System.arraycopy(objectSpill, 0, newObjectSpill, 0, oldLength);
+            if (primitiveSpill != null && newPrimitiveSpill != null) {
+                System.arraycopy(primitiveSpill, 0, newPrimitiveSpill, 0, oldLength);
             }
         }
 
         this.primitiveSpill = newPrimitiveSpill;
         this.objectSpill    = newObjectSpill;
-        this.spillLength = newLength;
 
         return this;
     }
@@ -3825,29 +3799,20 @@
     }
 
     /** This is updated only in debug mode - counts number of {@code ScriptObject} instances created */
-    private static int count;
+    private static LongAdder count;
 
-    /** This is updated only in debug mode - counts number of {@code ScriptObject} instances created that are scope */
-    private static int scopeCount;
-
+    static {
+        if (Context.DEBUG) {
+            count = new LongAdder();
+        }
+    }
     /**
      * Get number of {@code ScriptObject} instances created. If not running in debug
      * mode this is always 0
      *
      * @return number of ScriptObjects created
      */
-    public static int getCount() {
-        return count;
+    public static long getCount() {
+        return count.longValue();
     }
-
-    /**
-     * Get number of scope {@code ScriptObject} instances created. If not running in debug
-     * mode this is always 0
-     *
-     * @return number of scope ScriptObjects created
-     */
-    public static int getScopeCount() {
-        return scopeCount;
-    }
-
 }
diff --git a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java
index e927d4f..ae46d25 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java
@@ -32,6 +32,8 @@
 import static jdk.nashorn.internal.runtime.ECMAErrors.syntaxError;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsInt;
+import static jdk.nashorn.internal.runtime.JSType.isString;
+
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.SwitchPoint;
@@ -55,7 +57,6 @@
 import jdk.nashorn.internal.parser.Lexer;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
 
-
 /**
  * Utilities to be called by JavaScript runtime API and generated classes.
  */
@@ -114,6 +115,11 @@
     public static final Call THROW_REFERENCE_ERROR = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "throwReferenceError", void.class, String.class);
 
     /**
+     * Throws a reference error for an undefined variable.
+     */
+    public static final Call THROW_CONST_TYPE_ERROR = staticCall(MethodHandles.lookup(), ScriptRuntime.class, "throwConstTypeError", void.class, String.class);
+
+    /**
      * Used to invalidate builtin names, e.g "Function" mapping to all properties in Function.prototype and Function.prototype itself.
      */
     public static final Call INVALIDATE_RESERVED_BUILTIN_NAME = staticCallNoLookup(ScriptRuntime.class, "invalidateReservedBuiltinName", void.class, String.class);
@@ -367,9 +373,9 @@
      * @return prototype object after merge
      */
     public static ScriptObject mergeScope(final ScriptObject scope) {
-        final ScriptObject global = scope.getProto();
-        global.addBoundProperties(scope);
-        return global;
+        final ScriptObject parentScope = scope.getProto();
+        parentScope.addBoundProperties(scope);
+        return parentScope;
     }
 
     /**
@@ -402,6 +408,15 @@
     }
 
     /**
+     * Throws a type error for an assignment to a const.
+     *
+     * @param name the const name
+     */
+    public static void throwConstTypeError(final String name) {
+        throw typeError("assign.constant", name);
+    }
+
+    /**
      * Call a script function as a constructor with given args.
      *
      * @param target ScriptFunction object.
@@ -521,8 +536,6 @@
 
     /**
      * 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
      *
      * @param x  first term
      * @param y  second term
@@ -549,8 +562,7 @@
         final Object xPrim = JSType.toPrimitive(x);
         final Object yPrim = JSType.toPrimitive(y);
 
-        if (xPrim instanceof String || yPrim instanceof String
-                || xPrim instanceof ConsString || yPrim instanceof ConsString) {
+        if (isString(xPrim) || isString(yPrim)) {
             try {
                 return new ConsString(JSType.toCharSequence(xPrim), JSType.toCharSequence(yPrim));
             } catch (final IllegalArgumentException iae) {
@@ -673,6 +685,33 @@
     }
 
     /**
+     * ECMA 11.4.1 - delete operator, implementation for slow scopes
+     *
+     * This implementation of 'delete' walks the scope chain to find the scope that contains the
+     * property to be deleted, then invokes delete on it.
+     *
+     * @param obj       top scope object
+     * @param property  property to delete
+     * @param strict    are we in strict mode
+     *
+     * @return true if property was successfully found and deleted
+     */
+    public static boolean SLOW_DELETE(final Object obj, final Object property, final Object strict) {
+        if (obj instanceof ScriptObject) {
+            ScriptObject sobj = (ScriptObject) obj;
+            final String key = property.toString();
+            while (sobj != null && sobj.isScope()) {
+                final FindProperty find = sobj.findProperty(key, false);
+                if (find != null) {
+                    return sobj.delete(key, Boolean.TRUE.equals(strict));
+                }
+                sobj = sobj.getProto();
+            }
+        }
+        return DELETE(obj, property, strict);
+    }
+
+    /**
      * ECMA 11.4.1 - delete operator, special case
      *
      * This is 'delete' that always fails. We have to check strict mode and throw error.
@@ -720,7 +759,7 @@
             return true;
         }
         if (x instanceof ScriptObject && y instanceof ScriptObject) {
-            return x == y;
+            return false; // x != y
         }
         if (x instanceof ScriptObjectMirror || y instanceof ScriptObjectMirror) {
             return ScriptObjectMirror.identical(x, y);
@@ -784,37 +823,55 @@
      * @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) {
+        if (isUndefinedAndNull(xType, yType) || isUndefinedAndNull(yType, xType)) {
             return true;
-        }
-
-        if (xType == JSType.NUMBER && yType == JSType.STRING) {
-            return equals(x, JSType.toNumber(y));
-        }
-
-        if (xType == JSType.STRING && yType == JSType.NUMBER) {
-            return equals(JSType.toNumber(x), y);
-        }
-
-        if (xType == JSType.BOOLEAN) {
-            return equals(JSType.toNumber(x), y);
-        }
-
-        if (yType == JSType.BOOLEAN) {
-            return equals(x, JSType.toNumber(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 equals(JSType.toPrimitive(x), y);
+        } else if (isNumberAndString(xType, yType)) {
+            return equalNumberToString(x, y);
+        } else if (isNumberAndString(yType, xType)) {
+            // Can reverse order as both are primitives
+            return equalNumberToString(y, x);
+        } else if (xType == JSType.BOOLEAN) {
+            return equalBooleanToAny(x, y);
+        } else if (yType == JSType.BOOLEAN) {
+            // Can reverse order as y is primitive
+            return equalBooleanToAny(y, x);
+        } else if (isNumberOrStringAndObject(xType, yType)) {
+            return equalNumberOrStringToObject(x, y);
+        } else if (isNumberOrStringAndObject(yType, xType)) {
+            // Can reverse order as y is primitive
+            return equalNumberOrStringToObject(y, x);
         }
 
         return false;
     }
 
+    private static boolean isUndefinedAndNull(final JSType xType, final JSType yType) {
+        return xType == JSType.UNDEFINED && yType == JSType.NULL;
+    }
+
+    private static boolean isNumberAndString(final JSType xType, final JSType yType) {
+        return xType == JSType.NUMBER && yType == JSType.STRING;
+    }
+
+    private static boolean isNumberOrStringAndObject(final JSType xType, final JSType yType) {
+        return (xType == JSType.NUMBER || xType == JSType.STRING) && yType == JSType.OBJECT;
+    }
+
+    private static boolean equalNumberToString(final Object num, final Object str) {
+        // Specification says comparing a number to string should be done as "equals(num, JSType.toNumber(str))". We
+        // can short circuit it to this as we know that "num" is a number, so it'll end up being a number-number
+        // comparison.
+        return ((Number)num).doubleValue() == JSType.toNumber(str.toString());
+    }
+
+    private static boolean equalBooleanToAny(final Object bool, final Object any) {
+        return equals(JSType.toNumber((Boolean)bool), any);
+    }
+
+    private static boolean equalNumberOrStringToObject(final Object numOrStr, final Object any) {
+        return equals(numOrStr, JSType.toPrimitive(any));
+    }
+
     /**
      * ECMA 11.9.4 - The strict equal operator (===) - generic implementation
      *
@@ -921,8 +978,15 @@
      * @return true if x is less than y
      */
     public static boolean LT(final Object x, final Object y) {
-        final Object value = lessThan(x, y, true);
-        return value == UNDEFINED ? false : (Boolean)value;
+        final Object px = JSType.toPrimitive(x, Number.class);
+        final Object py = JSType.toPrimitive(y, Number.class);
+
+        return areBothString(px, py) ? px.toString().compareTo(py.toString()) < 0 :
+            JSType.toNumber(px) < JSType.toNumber(py);
+    }
+
+    private static boolean areBothString(final Object x, final Object y) {
+        return isString(x) && isString(y);
     }
 
     /**
@@ -934,8 +998,11 @@
      * @return true if x is greater than y
      */
     public static boolean GT(final Object x, final Object y) {
-        final Object value = lessThan(y, x, false);
-        return value == UNDEFINED ? false : (Boolean)value;
+        final Object px = JSType.toPrimitive(x, Number.class);
+        final Object py = JSType.toPrimitive(y, Number.class);
+
+        return areBothString(px, py) ? px.toString().compareTo(py.toString()) > 0 :
+            JSType.toNumber(px) > JSType.toNumber(py);
     }
 
     /**
@@ -947,8 +1014,11 @@
      * @return true if x is less than or equal to y
      */
     public static boolean LE(final Object x, final Object y) {
-        final Object value = lessThan(y, x, false);
-        return !(Boolean.TRUE.equals(value) || value == UNDEFINED);
+        final Object px = JSType.toPrimitive(x, Number.class);
+        final Object py = JSType.toPrimitive(y, Number.class);
+
+        return areBothString(px, py) ? px.toString().compareTo(py.toString()) <= 0 :
+            JSType.toNumber(px) <= JSType.toNumber(py);
     }
 
     /**
@@ -960,48 +1030,11 @@
      * @return true if x is greater than or equal to y
      */
     public static boolean GE(final Object x, final Object y) {
-        final Object value = lessThan(x, y, true);
-        return !(Boolean.TRUE.equals(value) || value == UNDEFINED);
-    }
+        final Object px = JSType.toPrimitive(x, Number.class);
+        final Object py = JSType.toPrimitive(y, Number.class);
 
-    /** ECMA 11.8.5 The Abstract Relational Comparison Algorithm */
-    private static Object lessThan(final Object x, final Object y, final boolean leftFirst) {
-        Object px, py;
-
-        //support e.g. x < y should throw exception correctly if x or y are not numeric
-        if (leftFirst) {
-            px = JSType.toPrimitive(x, Number.class);
-            py = JSType.toPrimitive(y, Number.class);
-        } else {
-            py = JSType.toPrimitive(y, Number.class);
-            px = JSType.toPrimitive(x, Number.class);
-        }
-
-        if (JSType.ofNoFunction(px) == JSType.STRING && JSType.ofNoFunction(py) == JSType.STRING) {
-            // May be String or ConsString
-            return px.toString().compareTo(py.toString()) < 0;
-        }
-
-        final double nx = JSType.toNumber(px);
-        final double ny = JSType.toNumber(py);
-
-        if (Double.isNaN(nx) || Double.isNaN(ny)) {
-            return UNDEFINED;
-        }
-
-        if (nx == ny) {
-            return false;
-        }
-
-        if (nx > 0 && ny > 0 && Double.isInfinite(nx) && Double.isInfinite(ny)) {
-            return false;
-        }
-
-        if (nx < 0 && ny < 0 && Double.isInfinite(nx) && Double.isInfinite(ny)) {
-            return false;
-        }
-
-        return nx < ny;
+        return areBothString(px, py) ? px.toString().compareTo(py.toString()) >= 0 :
+            JSType.toNumber(px) >= JSType.toNumber(py);
     }
 
     /**
@@ -1014,9 +1047,7 @@
         final Context context = Context.getContextTrusted();
         final SwitchPoint sp = context.getBuiltinSwitchPoint(name);
         assert sp != null;
-        if (sp != null) {
-            context.getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint");
-            SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
-        }
+        context.getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint");
+        SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
     }
 }
diff --git a/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java b/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java
index 8358323..d06c06f 100644
--- a/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java
+++ b/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 package jdk.nashorn.internal.runtime;
 
 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.ScriptRuntime.UNDEFINED;
 
@@ -34,10 +35,15 @@
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.io.OutputStreamWriter;
+import java.io.StreamTokenizer;
+import java.io.StringReader;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 import java.util.Map;
-import java.util.StringTokenizer;
+import jdk.nashorn.internal.objects.NativeArray;
 
 /**
  * Global functions supported only in scripting mode.
@@ -51,7 +57,7 @@
     public static final MethodHandle READFULLY = findOwnMH("readFully",     Object.class, Object.class, Object.class);
 
     /** Handle to implementation of {@link ScriptingFunctions#exec} - Nashorn extension */
-    public static final MethodHandle EXEC = findOwnMH("exec",     Object.class, Object.class, Object.class, Object.class);
+    public static final MethodHandle EXEC = findOwnMH("exec",     Object.class, Object.class, Object[].class);
 
     /** EXEC name - special property used by $EXEC API. */
     public static final String EXEC_NAME = "$EXEC";
@@ -65,10 +71,14 @@
     /** EXIT name - special property used by $EXEC API. */
     public static final String EXIT_NAME = "$EXIT";
 
+    /** THROW_ON_ERROR name - special property of the $EXEC function used by $EXEC API. */
+    public static final String THROW_ON_ERROR_NAME = "throwOnError";
+
     /** Names of special properties used by $ENV API. */
     public  static final String ENV_NAME  = "$ENV";
 
-    private static final String PWD_NAME  = "PWD";
+    /** Name of the environment variable for the current working directory. */
+    public static final String PWD_NAME  = "PWD";
 
     private ScriptingFunctions() {
     }
@@ -107,7 +117,7 @@
 
         if (file instanceof File) {
             f = (File)file;
-        } else if (file instanceof String || file instanceof ConsString) {
+        } else if (JSType.isString(file)) {
             f = new java.io.File(((CharSequence)file).toString());
         }
 
@@ -122,26 +132,32 @@
      * Nashorn extension: exec a string in a separate process.
      *
      * @param self   self reference
-     * @param string string to execute
-     * @param input  input
+     * @param args   string to execute, input and additional arguments, to be appended to {@code string}. Additional arguments can be passed as
+     *               either one JavaScript array, whose elements will be converted to strings; or as a sequence of
+     *               varargs, each of which will be converted to a string.
      *
      * @return output string from the request
+     *
      * @throws IOException           if any stream access fails
      * @throws InterruptedException  if execution is interrupted
      */
-    public static Object exec(final Object self, final Object string, final Object input) throws IOException, InterruptedException {
+    public static Object exec(final Object self, final Object... args) throws IOException, InterruptedException {
         // Current global is need to fetch additional inputs and for additional results.
         final ScriptObject global = Context.getGlobal();
-
-        // Break exec string into tokens.
-        final StringTokenizer tokenizer = new StringTokenizer(JSType.toString(string));
-        final String[] cmdArray = new String[tokenizer.countTokens()];
-        for (int i = 0; tokenizer.hasMoreTokens(); i++) {
-            cmdArray[i] = tokenizer.nextToken();
+        final Object string = args.length > 0? args[0] : UNDEFINED;
+        final Object input = args.length > 1? args[1] : UNDEFINED;
+        final Object[] argv = (args.length > 2)? Arrays.copyOfRange(args, 2, args.length) : ScriptRuntime.EMPTY_ARRAY;
+        // Assemble command line, process additional arguments.
+        final List<String> cmdLine = tokenizeString(JSType.toString(string));
+        final Object[] additionalArgs = argv.length == 1 && argv[0] instanceof NativeArray ?
+                ((NativeArray) argv[0]).asObjectArray() :
+                argv;
+        for (Object arg : additionalArgs) {
+            cmdLine.add(JSType.toString(arg));
         }
 
         // Set up initial process.
-        final ProcessBuilder processBuilder = new ProcessBuilder(cmdArray);
+        final ProcessBuilder processBuilder = new ProcessBuilder(cmdLine);
 
         // Current ENV property state.
         final Object env = global.get(ENV_NAME);
@@ -232,6 +248,19 @@
             }
         }
 
+        // if we got a non-zero exit code ("failure"), then we have to decide to throw error or not
+        if (exit != 0) {
+            // get the $EXEC function object from the global object
+            final Object exec = global.get(EXEC_NAME);
+            assert exec instanceof ScriptObject : EXEC_NAME + " is not a script object!";
+
+            // Check if the user has set $EXEC.throwOnError property to true. If so, throw RangeError
+            // If that property is not set or set to false, then silently proceed with the rest.
+            if (JSType.toBoolean(((ScriptObject)exec).get(THROW_ON_ERROR_NAME))) {
+                throw rangeError("exec.returned.non.zero", ScriptRuntime.safeToString(exit));
+            }
+        }
+
         // Return the result from stdout.
         return out;
     }
@@ -239,4 +268,42 @@
     private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
         return MH.findStatic(MethodHandles.lookup(), ScriptingFunctions.class, name, MH.type(rtype, types));
     }
+
+    /**
+     * Break a string into tokens, honoring quoted arguments and escaped spaces.
+     *
+     * @param str a {@link String} to tokenize.
+     * @return a {@link List} of {@link String}s representing the tokens that
+     * constitute the string.
+     * @throws IOException in case {@link StreamTokenizer#nextToken()} raises it.
+     */
+    public static List<String> tokenizeString(final String str) throws IOException {
+        final StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(str));
+        tokenizer.resetSyntax();
+        tokenizer.wordChars(0, 255);
+        tokenizer.whitespaceChars(0, ' ');
+        tokenizer.commentChar('#');
+        tokenizer.quoteChar('"');
+        tokenizer.quoteChar('\'');
+        final List<String> tokenList = new ArrayList<>();
+        final StringBuilder toAppend = new StringBuilder();
+        while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) {
+            final String s = tokenizer.sval;
+            // The tokenizer understands about honoring quoted strings and recognizes
+            // them as one token that possibly contains multiple space-separated words.
+            // It does not recognize quoted spaces, though, and will split after the
+            // escaping \ character. This is handled here.
+            if (s.endsWith("\\")) {
+                // omit trailing \, append space instead
+                toAppend.append(s.substring(0, s.length() - 1)).append(' ');
+            } else {
+                tokenList.add(toAppend.append(s).toString());
+                toAppend.setLength(0);
+            }
+        }
+        if (toAppend.length() != 0) {
+            tokenList.add(toAppend.toString());
+        }
+        return tokenList;
+    }
 }
diff --git a/src/jdk/nashorn/internal/runtime/SetMethodCreator.java b/src/jdk/nashorn/internal/runtime/SetMethodCreator.java
index 90bbf43..4427930 100644
--- a/src/jdk/nashorn/internal/runtime/SetMethodCreator.java
+++ b/src/jdk/nashorn/internal/runtime/SetMethodCreator.java
@@ -186,10 +186,7 @@
 
     private SetMethod createNewPropertySetter(final SwitchPoint builtinSwitchPoint) {
         final SetMethod sm = map.getFreeFieldSlot() > -1 ? createNewFieldSetter(builtinSwitchPoint) : createNewSpillPropertySetter(builtinSwitchPoint);
-        final PropertyListeners listeners = map.getListeners();
-        if (listeners != null) {
-            listeners.propertyAdded(sm.property);
-        }
+        map.propertyAdded(sm.property, true);
         return sm;
     }
 
@@ -204,7 +201,7 @@
         //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
+        //slow setter, that calls ScriptObject.set with appropriate type and key name
         MethodHandle slowSetter = ScriptObject.SET_SLOW[getAccessorTypeIndex(type)];
         slowSetter = MH.insertArguments(slowSetter, 3, NashornCallSiteDescriptor.getFlags(desc));
         slowSetter = MH.insertArguments(slowSetter, 1, name);
@@ -232,14 +229,18 @@
     }
 
     private SetMethod createNewFieldSetter(final SwitchPoint builtinSwitchPoint) {
-        return createNewSetter(new AccessorProperty(getName(), 0, sobj.getClass(), getMap().getFreeFieldSlot(), type), builtinSwitchPoint);
+        return createNewSetter(new AccessorProperty(getName(), getFlags(sobj), sobj.getClass(), getMap().getFreeFieldSlot(), type), builtinSwitchPoint);
     }
 
     private SetMethod createNewSpillPropertySetter(final SwitchPoint builtinSwitchPoint) {
-        return createNewSetter(new SpillProperty(getName(), 0, getMap().getFreeSpillSlot(), type), builtinSwitchPoint);
+        return createNewSetter(new SpillProperty(getName(), getFlags(sobj), getMap().getFreeSpillSlot(), type), builtinSwitchPoint);
     }
 
     private PropertyMap getNewMap(final Property property) {
         return getMap().addProperty(property);
     }
+
+    private static int getFlags(final ScriptObject scriptObject) {
+        return scriptObject.useDualFields() ? Property.DUAL_FIELDS : 0;
+    }
 }
diff --git a/src/jdk/nashorn/internal/runtime/SharedPropertyMap.java b/src/jdk/nashorn/internal/runtime/SharedPropertyMap.java
new file mode 100644
index 0000000..215d0c8
--- /dev/null
+++ b/src/jdk/nashorn/internal/runtime/SharedPropertyMap.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.SwitchPoint;
+
+/**
+ * This class represents a property map that can be shared among multiple prototype objects, allowing all inheriting
+ * top-level objects to also share one property map. This is class is only used for prototype objects, the
+ * top-level objects use ordinary {@link PropertyMap}s with the {@link PropertyMap#sharedProtoMap} field
+ * set to the expected shared prototype map.
+ *
+ * <p>When an instance of this class is evolved because a property is added, removed, or modified in an object
+ * using it, the {@link #invalidateSwitchPoint()} method is invoked to signal to all callsites and inheriting
+ * objects that the assumption of a single shared prototype map is no longer valid. The property map resulting
+ * from the modification will no longer be an instance of this class.</p>
+ */
+public final class SharedPropertyMap extends PropertyMap {
+
+    private SwitchPoint switchPoint;
+
+    private static final long serialVersionUID = 2166297719721778876L;
+
+    /**
+     * Create a new shared property map from the given {@code map}.
+     * @param map property map to copy
+     */
+    public SharedPropertyMap(final PropertyMap map) {
+        super(map);
+        this.switchPoint = new SwitchPoint();
+    }
+
+    @Override
+    public void propertyAdded(final Property property, final boolean isSelf) {
+        if (isSelf) {
+            invalidateSwitchPoint();
+        }
+        super.propertyAdded(property, isSelf);
+    }
+
+    @Override
+    public void propertyDeleted(final Property property, final boolean isSelf) {
+        if (isSelf) {
+            invalidateSwitchPoint();
+        }
+        super.propertyDeleted(property, isSelf);
+    }
+
+    @Override
+    public void propertyModified(final Property oldProperty, final Property newProperty, final boolean isSelf) {
+        if (isSelf) {
+            invalidateSwitchPoint();
+        }
+        super.propertyModified(oldProperty, newProperty, isSelf);
+    }
+
+    @Override
+    synchronized boolean isValidSharedProtoMap() {
+        return switchPoint != null;
+    }
+
+    @Override
+    synchronized SwitchPoint getSharedProtoSwitchPoint() {
+        return switchPoint;
+    }
+
+    /**
+     * Invalidate the shared prototype switch point if this is a shared prototype map.
+     */
+    synchronized void invalidateSwitchPoint() {
+        if (switchPoint != null) {
+            assert !switchPoint.hasBeenInvalidated();
+            SwitchPoint.invalidateAll(new SwitchPoint[]{ switchPoint });
+            switchPoint = null;
+        }
+    }
+}
diff --git a/src/jdk/nashorn/internal/runtime/Source.java b/src/jdk/nashorn/internal/runtime/Source.java
index 38d4b85..b2ffbe6 100644
--- a/src/jdk/nashorn/internal/runtime/Source.java
+++ b/src/jdk/nashorn/internal/runtime/Source.java
@@ -28,9 +28,11 @@
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.IOError;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.PrintWriter;
 import java.io.Reader;
 import java.lang.ref.WeakReference;
 import java.net.MalformedURLException;
@@ -44,6 +46,7 @@
 import java.nio.file.Paths;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.time.LocalDateTime;
 import java.util.Arrays;
 import java.util.Base64;
 import java.util.Objects;
@@ -907,14 +910,16 @@
             start = 2;
             cs = StandardCharsets.UTF_16BE;
         } else if (bytes.length > 1 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE) {
-            start = 2;
-            cs = StandardCharsets.UTF_16LE;
+            if (bytes.length > 3 && bytes[2] == 0 && bytes[3] == 0) {
+                start = 4;
+                cs = Charset.forName("UTF-32LE");
+            } else {
+                start = 2;
+                cs = StandardCharsets.UTF_16LE;
+            }
         } else if (bytes.length > 2 && bytes[0] == (byte) 0xEF && bytes[1] == (byte) 0xBB && bytes[2] == (byte) 0xBF) {
             start = 3;
             cs = StandardCharsets.UTF_8;
-        } else if (bytes.length > 3 && bytes[0] == (byte) 0xFF && bytes[1] == (byte) 0xFE && bytes[2] == 0 && bytes[3] == 0) {
-            start = 4;
-            cs = Charset.forName("UTF-32LE");
         } else if (bytes.length > 3 && bytes[0] == 0 && bytes[1] == 0 && bytes[2] == (byte) 0xFE && bytes[3] == (byte) 0xFF) {
             start = 4;
             cs = Charset.forName("UTF-32BE");
@@ -965,4 +970,45 @@
     public DebugLogger getLogger() {
         return initLogger(Context.getContextTrusted());
     }
+
+    private File dumpFile(final File dirFile) {
+        final URL u = getURL();
+        final StringBuilder buf = new StringBuilder();
+        // make it unique by prefixing current date & time
+        buf.append(LocalDateTime.now().toString());
+        buf.append('_');
+        if (u != null) {
+            // make it a safe file name
+            buf.append(u.toString()
+                    .replace('/', '_')
+                    .replace('\\', '_'));
+        } else {
+            buf.append(getName());
+        }
+
+        return new File(dirFile, buf.toString());
+    }
+
+    void dump(final String dir) {
+        final File dirFile = new File(dir);
+        final File file = dumpFile(dirFile);
+        if (!dirFile.exists() && !dirFile.mkdirs()) {
+            debug("Skipping source dump for " + name);
+            return;
+        }
+
+        try (final FileOutputStream fos = new FileOutputStream(file)) {
+            final PrintWriter pw = new PrintWriter(fos);
+            pw.print(data.toString());
+            pw.flush();
+        } catch (final IOException ioExp) {
+            debug("Skipping source dump for " +
+                    name +
+                    ": " +
+                    ECMAErrors.getMessage(
+                        "io.error.cant.write",
+                        dir.toString() +
+                        " : " + ioExp.toString()));
+        }
+    }
 }
diff --git a/src/jdk/nashorn/internal/runtime/SpillProperty.java b/src/jdk/nashorn/internal/runtime/SpillProperty.java
index 7b42b2b..9019b56 100644
--- a/src/jdk/nashorn/internal/runtime/SpillProperty.java
+++ b/src/jdk/nashorn/internal/runtime/SpillProperty.java
@@ -25,7 +25,6 @@
 
 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;
@@ -139,11 +138,11 @@
         }
     }
 
-    private static MethodHandle primitiveGetter(final int slot) {
-        return OBJECT_FIELDS_ONLY ? null : Accessors.getCached(slot, true, true);
+    private static MethodHandle primitiveGetter(final int slot, final int flags) {
+        return (flags & DUAL_FIELDS) == DUAL_FIELDS ? Accessors.getCached(slot, true, true) : null;
     }
-    private static MethodHandle primitiveSetter(final int slot) {
-        return OBJECT_FIELDS_ONLY ? null : Accessors.getCached(slot, true, false);
+    private static MethodHandle primitiveSetter(final int slot, final int flags) {
+        return (flags & DUAL_FIELDS) == DUAL_FIELDS ? Accessors.getCached(slot, true, false) : null;
     }
     private static MethodHandle objectGetter(final int slot) {
         return Accessors.getCached(slot, false, true);
@@ -160,13 +159,19 @@
      * @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 || getLocalType() == Object.class;
+        super(key, flags, slot, primitiveGetter(slot, flags), primitiveSetter(slot, flags), objectGetter(slot), objectSetter(slot));
     }
 
-    SpillProperty(final String key, final int flags, final int slot, final Class<?> initialType) {
+    /**
+     * Constructor for spill properties with an initial type.
+     * @param key         the property key
+     * @param flags       the property flags
+     * @param slot        spill slot
+     * @param initialType initial type
+     */
+    public SpillProperty(final String key, final int flags, final int slot, final Class<?> initialType) {
         this(key, flags, slot);
-        setType(OBJECT_FIELDS_ONLY ? Object.class : initialType);
+        setType(hasDualFields() ? initialType : Object.class);
     }
 
     SpillProperty(final String key, final int flags, final int slot, final ScriptObject owner, final Object initialValue) {
@@ -209,8 +214,8 @@
     @Override
     void initMethodHandles(final Class<?> structure) {
         final int slot  = getSlot();
-        primitiveGetter = primitiveGetter(slot);
-        primitiveSetter = primitiveSetter(slot);
+        primitiveGetter = primitiveGetter(slot, getFlags());
+        primitiveSetter = primitiveSetter(slot, getFlags());
         objectGetter    = objectGetter(slot);
         objectSetter    = objectSetter(slot);
     }
diff --git a/src/jdk/nashorn/internal/runtime/StoredScript.java b/src/jdk/nashorn/internal/runtime/StoredScript.java
index 14a0ced..eea01e7 100644
--- a/src/jdk/nashorn/internal/runtime/StoredScript.java
+++ b/src/jdk/nashorn/internal/runtime/StoredScript.java
@@ -27,7 +27,7 @@
 
 import java.io.Serializable;
 import java.util.Arrays;
-import java.util.LinkedHashMap;
+import java.util.HashMap;
 import java.util.Map;
 
 /**
@@ -58,7 +58,7 @@
      * @param compilationId compilation id
      * @param mainClassName main class name
      * @param classBytes map of class names to class bytes
-     * @param initializers initializer map, id -> FunctionInitializer
+     * @param initializers initializer map, id -&gt; FunctionInitializer
      * @param constants constants array
      */
     public StoredScript(final int compilationId, final String mainClassName, final Map<String, byte[]> classBytes, final Map<Integer, FunctionInitializer> initializers, final Object[] constants) {
@@ -77,44 +77,70 @@
         return compilationId;
     }
 
-    /**
-     * Returns the main class name.
-     * @return the main class name
-     */
-    public String getMainClassName() {
-        return mainClassName;
-    }
+    private Map<String, Class<?>> installClasses(final Source source, final CodeInstaller installer) {
+        final Map<String, Class<?>> installedClasses = new HashMap<>();
+        final byte[]   mainClassBytes = classBytes.get(mainClassName);
+        final Class<?> mainClass      = installer.install(mainClassName, mainClassBytes);
 
-    /**
-     * Returns a map of class names to class bytes.
-     * @return map of class bytes
-     */
-    public Map<String, byte[]> getClassBytes() {
-        final Map<String, byte[]> clonedMap = new LinkedHashMap<>();
+        installedClasses.put(mainClassName, mainClass);
+
         for (final Map.Entry<String, byte[]> entry : classBytes.entrySet()) {
-            clonedMap.put(entry.getKey(), entry.getValue().clone());
+            final String className = entry.getKey();
+
+            if (!className.equals(mainClassName)) {
+                installedClasses.put(className, installer.install(className, entry.getValue()));
+            }
         }
-        return clonedMap;
+
+        installer.initialize(installedClasses.values(), source, constants);
+        return installedClasses;
+    }
+
+    FunctionInitializer installFunction(final RecompilableScriptFunctionData data, final CodeInstaller installer) {
+        final Map<String, Class<?>> installedClasses = installClasses(data.getSource(), installer);
+
+        assert initializers != null;
+        assert initializers.size() == 1;
+        final FunctionInitializer initializer = initializers.values().iterator().next();
+
+        for (int i = 0; i < constants.length; i++) {
+            if (constants[i] instanceof RecompilableScriptFunctionData) {
+                // replace deserialized function data with the ones we already have
+                final RecompilableScriptFunctionData newData = data.getScriptFunctionData(((RecompilableScriptFunctionData) constants[i]).getFunctionNodeId());
+                assert newData != null;
+                newData.initTransients(data.getSource(), installer);
+                constants[i] = newData;
+            }
+        }
+
+        initializer.setCode(installedClasses.get(initializer.getClassName()));
+        return initializer;
     }
 
     /**
-     * Returns the constants array.
-     * @return constants array
+     * Install as script.
+     *
+     * @param source the source
+     * @param installer the installer
+     * @return main script class
      */
-    public Object[] getConstants() {
-        return constants.clone();
-    }
+    Class<?> installScript(final Source source, final CodeInstaller installer) {
 
-    /**
-     * Returns the function initializers map.
-     * @return The initializers map.
-     */
-    public Map<Integer, FunctionInitializer> getInitializers() {
-        final Map<Integer, FunctionInitializer> clonedMap = new LinkedHashMap<>();
-        for (final Map.Entry<Integer, FunctionInitializer> entry : initializers.entrySet()) {
-            clonedMap.put(entry.getKey(), new FunctionInitializer(entry.getValue()));
+        final Map<String, Class<?>> installedClasses = installClasses(source, installer);
+
+        for (final Object constant : constants) {
+            if (constant instanceof RecompilableScriptFunctionData) {
+                final RecompilableScriptFunctionData data = (RecompilableScriptFunctionData) constant;
+                data.initTransients(source, installer);
+                final FunctionInitializer initializer = initializers.get(data.getFunctionNodeId());
+                if (initializer != null) {
+                    initializer.setCode(installedClasses.get(initializer.getClassName()));
+                    data.initializeCode(initializer);
+                }
+            }
         }
-        return clonedMap;
+
+        return installedClasses.get(mainClassName);
     }
 
     @Override
diff --git a/src/jdk/nashorn/internal/runtime/StructureLoader.java b/src/jdk/nashorn/internal/runtime/StructureLoader.java
index 41201cd..8324730 100644
--- a/src/jdk/nashorn/internal/runtime/StructureLoader.java
+++ b/src/jdk/nashorn/internal/runtime/StructureLoader.java
@@ -27,7 +27,8 @@
 
 import static jdk.nashorn.internal.codegen.Compiler.SCRIPTS_PACKAGE;
 import static jdk.nashorn.internal.codegen.Compiler.binaryName;
-import static jdk.nashorn.internal.codegen.CompilerConstants.JS_OBJECT_PREFIX;
+import static jdk.nashorn.internal.codegen.CompilerConstants.JS_OBJECT_DUAL_FIELD_PREFIX;
+import static jdk.nashorn.internal.codegen.CompilerConstants.JS_OBJECT_SINGLE_FIELD_PREFIX;
 
 import java.security.ProtectionDomain;
 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
@@ -36,7 +37,8 @@
  * Responsible for on the fly construction of structure classes.
  */
 final class StructureLoader extends NashornLoader {
-    private static final String JS_OBJECT_PREFIX_EXTERNAL = binaryName(SCRIPTS_PACKAGE) + '.' + JS_OBJECT_PREFIX.symbolName();
+    private static final String SINGLE_FIELD_PREFIX = binaryName(SCRIPTS_PACKAGE) + '.' + JS_OBJECT_SINGLE_FIELD_PREFIX.symbolName();
+    private static final String DUAL_FIELD_PREFIX   = binaryName(SCRIPTS_PACKAGE) + '.' + JS_OBJECT_DUAL_FIELD_PREFIX.symbolName();
 
     /**
      * Constructor.
@@ -45,14 +47,39 @@
         super(parent);
     }
 
+    /**
+     * Returns true if the class name represents a structure object with dual primitive/object fields.
+     * @param name a class name
+     * @return true if a dual field structure class
+     */
+    private static boolean isDualFieldStructure(final String name) {
+        return name.startsWith(DUAL_FIELD_PREFIX);
+    }
+
+    /**
+     * Returns true if the class name represents a structure object with single object-only fields.
+     * @param name a class name
+     * @return true if a single field structure class
+     */
+    static boolean isSingleFieldStructure(final String name) {
+        return name.startsWith(SINGLE_FIELD_PREFIX);
+    }
+
+    /**
+     * Returns true if the class name represents a Nashorn structure object.
+     * @param name a class name
+     * @return true if a structure class
+     */
     static boolean isStructureClass(final String name) {
-        return name.startsWith(JS_OBJECT_PREFIX_EXTERNAL);
+        return isDualFieldStructure(name) || isSingleFieldStructure(name);
     }
 
     @Override
     protected Class<?> findClass(final String name) throws ClassNotFoundException {
-        if (isStructureClass(name)) {
-            return generateClass(name, name.substring(JS_OBJECT_PREFIX_EXTERNAL.length()));
+        if (isDualFieldStructure(name)) {
+            return generateClass(name, name.substring(DUAL_FIELD_PREFIX.length()), true);
+        } else if (isSingleFieldStructure(name)) {
+            return generateClass(name, name.substring(SINGLE_FIELD_PREFIX.length()), false);
         }
         return super.findClass(name);
     }
@@ -63,10 +90,10 @@
      * @param descriptor Layout descriptor.
      * @return Generated class.
      */
-    private Class<?> generateClass(final String name, final String descriptor) {
+    private Class<?> generateClass(final String name, final String descriptor, final boolean dualFields) {
         final Context context = Context.getContextTrusted();
 
-        final byte[] code = new ObjectClassGenerator(context).generate(descriptor);
+        final byte[] code = new ObjectClassGenerator(context, dualFields).generate(descriptor);
         return defineClass(name, code, 0, code.length, new ProtectionDomain(null, getPermissions(null)));
     }
 }
diff --git a/src/jdk/nashorn/internal/runtime/Timing.java b/src/jdk/nashorn/internal/runtime/Timing.java
index e1d464d..d4a5280 100644
--- a/src/jdk/nashorn/internal/runtime/Timing.java
+++ b/src/jdk/nashorn/internal/runtime/Timing.java
@@ -28,12 +28,14 @@
 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 java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.LongAdder;
+import java.util.function.Function;
 import java.util.function.Supplier;
-
 import jdk.nashorn.internal.codegen.CompileUnit;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.logging.Loggable;
@@ -156,11 +158,15 @@
     }
 
     final class TimeSupplier implements Supplier<String> {
-        private final Map<String, Long> timings;
-
-        TimeSupplier() {
-            timings   = new LinkedHashMap<>();
-        }
+        private final Map<String, LongAdder> timings = new ConcurrentHashMap<>();
+        private final LinkedBlockingQueue<String> orderedTimingNames = new LinkedBlockingQueue<>();
+        private final Function<String, LongAdder> newTimingCreator = new Function<String, LongAdder>() {
+            @Override
+            public LongAdder apply(final String s) {
+                orderedTimingNames.add(s);
+                return new LongAdder();
+            }
+        };
 
         String[] getStrings() {
             final List<String> strs = new ArrayList<>();
@@ -184,26 +190,26 @@
             int  maxKeyLength = 0;
             int  maxValueLength = 0;
 
-            for (final Map.Entry<String, Long> entry : timings.entrySet()) {
+            for (final Map.Entry<String, LongAdder> entry : timings.entrySet()) {
                 maxKeyLength   = Math.max(maxKeyLength, entry.getKey().length());
-                maxValueLength = Math.max(maxValueLength, toMillisPrint(entry.getValue()).length());
+                maxValueLength = Math.max(maxValueLength, toMillisPrint(entry.getValue().longValue()).length());
             }
             maxKeyLength++;
 
             final StringBuilder sb = new StringBuilder();
             sb.append("Accumulated compilation phase timings:\n\n");
-            for (final Map.Entry<String, Long> entry : timings.entrySet()) {
+            for (final String timingName: orderedTimingNames) {
                 int len;
 
                 len = sb.length();
-                sb.append(entry.getKey());
+                sb.append(timingName);
                 len = sb.length() - len;
 
                 while (len++ < maxKeyLength) {
                     sb.append(' ');
                 }
 
-                final Long duration = entry.getValue();
+                final long duration = timings.get(timingName).longValue();
                 final String strDuration = toMillisPrint(duration);
                 len = strDuration.length();
                 for (int i = 0; i < maxValueLength - len; i++) {
@@ -233,11 +239,7 @@
         }
 
         private void accumulateTime(final String module, final long duration) {
-            Long accumulatedTime = timings.get(module);
-            if (accumulatedTime == null) {
-                accumulatedTime = 0L;
-            }
-            timings.put(module, accumulatedTime + duration);
+            timings.computeIfAbsent(module, newTimingCreator).add(duration);
         }
     }
 }
diff --git a/src/jdk/nashorn/internal/runtime/Undefined.java b/src/jdk/nashorn/internal/runtime/Undefined.java
index 57c7e5f..db26bcd 100644
--- a/src/jdk/nashorn/internal/runtime/Undefined.java
+++ b/src/jdk/nashorn/internal/runtime/Undefined.java
@@ -96,8 +96,12 @@
 
         switch (operator) {
         case "new":
-        case "call":
-            throw lookupTypeError("cant.call.undefined", desc);
+        case "call": {
+            final String name = NashornCallSiteDescriptor.getFunctionDescription(desc);
+            final String msg = name != null? "not.a.function" : "cant.call.undefined";
+            throw typeError(msg, name);
+        }
+
         case "callMethod":
             throw lookupTypeError("cant.read.property.of.undefined", desc);
         // NOTE: we support getElem and setItem as JavaScript doesn't distinguish items from properties. Nashorn itself
@@ -125,7 +129,8 @@
     }
 
     private static ECMAException lookupTypeError(final String msg, final CallSiteDescriptor desc) {
-        return typeError(msg, desc.getNameTokenCount() > 2 ? desc.getNameToken(2) : null);
+        final String name = desc.getNameToken(2);
+        return typeError(msg, name != null && !name.isEmpty()? name : null);
     }
 
     private static final MethodHandle GET_METHOD = findOwnMH("get", Object.class, Object.class);
diff --git a/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java b/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java
index d14dd8e..5313d78 100644
--- a/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java
+++ b/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java
@@ -24,7 +24,6 @@
  */
 
 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;
@@ -34,6 +33,7 @@
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
+import java.util.concurrent.Callable;
 import jdk.nashorn.internal.lookup.Lookup;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
@@ -80,6 +80,15 @@
     private final static MethodHandle INVOKE_LONG_SETTER = findOwnMH_S("invokeLongSetter", void.class, Accessors.class, MethodHandle.class, String.class, Object.class, long.class);
     private final static MethodHandle INVOKE_NUMBER_SETTER = findOwnMH_S("invokeNumberSetter", void.class, Accessors.class, MethodHandle.class, String.class, Object.class, double.class);
 
+    private static final Object OBJECT_GETTER_INVOKER_KEY = new Object();
+    private static MethodHandle getObjectGetterInvoker() {
+        return Context.getGlobal().getDynamicInvoker(OBJECT_GETTER_INVOKER_KEY, new Callable<MethodHandle>() {
+            @Override
+            public MethodHandle call() throws Exception {
+                return getINVOKE_UA_GETTER(Object.class, INVALID_PROGRAM_POINT);
+            }
+        });
+    }
 
     static MethodHandle getINVOKE_UA_GETTER(final Class<?> returnType, final int programPoint) {
         if (UnwarrantedOptimismException.isValid(programPoint)) {
@@ -90,6 +99,16 @@
         }
     }
 
+    private static final Object OBJECT_SETTER_INVOKER_KEY = new Object();
+    private static MethodHandle getObjectSetterInvoker() {
+        return Context.getGlobal().getDynamicInvoker(OBJECT_SETTER_INVOKER_KEY, new Callable<MethodHandle>() {
+            @Override
+            public MethodHandle call() throws Exception {
+                return getINVOKE_UA_SETTER(Object.class);
+            }
+        });
+    }
+
     static MethodHandle getINVOKE_UA_SETTER(final Class<?> valueType) {
         return Bootstrap.createDynamicInvoker("dyn:call", void.class, Object.class, Object.class, valueType);
     }
@@ -181,7 +200,7 @@
     @Override
     public Object getObjectValue(final ScriptObject self, final ScriptObject owner) {
         try {
-            return invokeObjectGetter(getAccessors((owner != null) ? owner : self), getINVOKE_UA_GETTER(Object.class, INVALID_PROGRAM_POINT), self);
+            return invokeObjectGetter(getAccessors((owner != null) ? owner : self), getObjectGetterInvoker(), self);
         } catch (final Error | RuntimeException t) {
             throw t;
         } catch (final Throwable t) {
@@ -207,7 +226,7 @@
     @Override
     public void setValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict) {
         try {
-            invokeObjectSetter(getAccessors((owner != null) ? owner : self), getINVOKE_UA_SETTER(Object.class), strict ? getKey() : null, self, value);
+            invokeObjectSetter(getAccessors((owner != null) ? owner : self), getObjectSetterInvoker(), strict ? getKey() : null, self, value);
         } catch (final Error | RuntimeException t) {
             throw t;
         } catch (final Throwable t) {
diff --git a/src/jdk/nashorn/internal/runtime/WithObject.java b/src/jdk/nashorn/internal/runtime/WithObject.java
index 20510df..1780e3f 100644
--- a/src/jdk/nashorn/internal/runtime/WithObject.java
+++ b/src/jdk/nashorn/internal/runtime/WithObject.java
@@ -26,6 +26,7 @@
 package jdk.nashorn.internal.runtime;
 
 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;
@@ -44,8 +45,8 @@
  * This class supports the handling of scope in a with body.
  *
  */
-public final class WithObject extends ScriptObject implements Scope {
-    private static final MethodHandle WITHEXPRESSIONGUARD    = findOwnMH("withExpressionGuard",  boolean.class, Object.class, PropertyMap.class, SwitchPoint.class);
+public final class WithObject extends Scope {
+    private static final MethodHandle WITHEXPRESSIONGUARD    = findOwnMH("withExpressionGuard",  boolean.class, Object.class, PropertyMap.class, SwitchPoint[].class);
     private static final MethodHandle WITHEXPRESSIONFILTER   = findOwnMH("withFilterExpression", Object.class, Object.class);
     private static final MethodHandle WITHSCOPEFILTER        = findOwnMH("withFilterScope",      Object.class, Object.class);
     private static final MethodHandle BIND_TO_EXPRESSION_OBJ = findOwnMH("bindToExpression",     Object.class, Object.class, Object.class);
@@ -62,7 +63,6 @@
      */
     WithObject(final ScriptObject scope, final ScriptObject expression) {
         super(scope, null);
-        setIsScope();
         this.expression = expression;
     }
 
@@ -198,7 +198,7 @@
      * @return FindPropertyData or null if not found.
      */
     @Override
-    FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) {
+    protected FindProperty findProperty(final String key, final boolean deep, final ScriptObject start) {
         // We call findProperty on 'expression' with 'expression' itself as start parameter.
         // This way in ScriptObject.setObject we can tell the property is from a 'with' expression
         // (as opposed from another non-scope object in the proto chain such as Object.prototype).
@@ -210,43 +210,49 @@
     }
 
     @Override
-    protected Object invokeNoSuchProperty(final String name, final int programPoint) {
+    protected Object invokeNoSuchProperty(final String name, final boolean isScope, final int programPoint) {
         FindProperty find = expression.findProperty(NO_SUCH_PROPERTY_NAME, true);
         if (find != null) {
             final Object func = find.getObjectValue();
             if (func instanceof ScriptFunction) {
-                return ScriptRuntime.apply((ScriptFunction)func, expression, name);
+                final ScriptFunction sfunc = (ScriptFunction)func;
+                final Object self = isScope && sfunc.isStrict()? UNDEFINED : expression;
+                return ScriptRuntime.apply(sfunc, self, name);
             }
         }
 
-        return getProto().invokeNoSuchProperty(name, programPoint);
+        return getProto().invokeNoSuchProperty(name, isScope, programPoint);
     }
 
     @Override
     public void setSplitState(final int state) {
-        getNonWithParent().setSplitState(state);
+        ((Scope) getNonWithParent()).setSplitState(state);
     }
 
     @Override
     public int getSplitState() {
-        return getNonWithParent().getSplitState();
+        return ((Scope) getNonWithParent()).getSplitState();
+    }
+
+    @Override
+    public void addBoundProperties(final ScriptObject source, final Property[] properties) {
+        // Declared variables in nested eval go to first normal (non-with) parent scope.
+        getNonWithParent().addBoundProperties(source, properties);
     }
 
     /**
      * Get first parent scope that is not an instance of WithObject.
      */
-    private Scope getNonWithParent() {
-        ScriptObject proto = getParentScope();
+    private ScriptObject getNonWithParent() {
+        ScriptObject proto = getProto();
 
         while (proto != null && proto instanceof WithObject) {
-            proto = ((WithObject)proto).getParentScope();
+            proto = proto.getProto();
         }
 
-        assert proto instanceof Scope : "with scope without parent scope";
-        return (Scope) proto;
+        return proto;
     }
 
-
     private static GuardedInvocation fixReceiverType(final GuardedInvocation link, final MethodHandle filter) {
         // The receiver may be an Object or a ScriptObject.
         final MethodType invType = link.getInvocation().type();
@@ -349,18 +355,29 @@
     }
 
     private static Object bindToExpression(final ScriptFunction fn, final Object receiver) {
-        return fn.makeBoundFunction(withFilterExpression(receiver), ScriptRuntime.EMPTY_ARRAY);
+        return fn.createBound(withFilterExpression(receiver), ScriptRuntime.EMPTY_ARRAY);
     }
 
     private MethodHandle expressionGuard(final String name, final ScriptObject owner) {
         final PropertyMap map = expression.getMap();
-        final SwitchPoint sp = expression.getProtoSwitchPoint(name, owner);
+        final SwitchPoint[] sp = expression.getProtoSwitchPoints(name, owner);
         return MH.insertArguments(WITHEXPRESSIONGUARD, 1, map, sp);
     }
 
     @SuppressWarnings("unused")
-    private static boolean withExpressionGuard(final Object receiver, final PropertyMap map, final SwitchPoint sp) {
-        return ((WithObject)receiver).expression.getMap() == map && (sp == null || !sp.hasBeenInvalidated());
+    private static boolean withExpressionGuard(final Object receiver, final PropertyMap map, final SwitchPoint[] sp) {
+        return ((WithObject)receiver).expression.getMap() == map && !hasBeenInvalidated(sp);
+    }
+
+    private static boolean hasBeenInvalidated(final SwitchPoint[] switchPoints) {
+        if (switchPoints != null) {
+            for (final SwitchPoint switchPoint : switchPoints) {
+                if (switchPoint.hasBeenInvalidated()) {
+                    return true;
+                }
+            }
+        }
+        return false;
     }
 
     /**
@@ -380,14 +397,6 @@
         return expression;
     }
 
-    /**
-     * Get the parent scope for this {@code WithObject}
-     * @return the parent scope
-     */
-    public ScriptObject getParentScope() {
-        return getProto();
-    }
-
     private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
         return MH.findStatic(MethodHandles.lookup(), WithObject.class, name, MH.type(rtype, types));
     }
diff --git a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java
index f0a8c7a..91fa4b3 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java
@@ -26,6 +26,7 @@
 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.lang.reflect.Array;
@@ -117,7 +118,7 @@
                     return new SparseArrayData(this, safeIndex + 1);
                 }
                 //known to fit in int
-                return toRealArrayData((int)safeIndex).ensure(safeIndex);
+                return toRealArrayData((int)safeIndex);
            }
            return this;
         }
@@ -257,7 +258,7 @@
      * Factory method for unspecified array - start as int
      * @return ArrayData
      */
-    public final static ArrayData initialArray() {
+    public static ArrayData initialArray() {
         return new IntArrayData();
     }
 
@@ -275,9 +276,9 @@
     /**
      * Align an array size up to the nearest array chunk size
      * @param size size required
-     * @return size given, always >= size
+     * @return size given, always &gt;= size
      */
-    protected final static int alignUp(final int size) {
+    protected static int alignUp(final int size) {
         return size + CHUNK_SIZE - 1 & ~(CHUNK_SIZE - 1);
     }
 
@@ -287,7 +288,7 @@
      * @param length the initial length
      * @return ArrayData
      */
-    public static final ArrayData allocate(final int length) {
+    public static ArrayData allocate(final int length) {
         if (length == 0) {
             return new IntArrayData();
         } else if (length >= SparseArrayData.MAX_DENSE_LENGTH) {
@@ -303,7 +304,7 @@
      * @param  array the array
      * @return ArrayData wrapping this array
      */
-    public static final ArrayData allocate(final Object array) {
+    public static ArrayData allocate(final Object array) {
         final Class<?> clazz = array.getClass();
 
         if (clazz == int[].class) {
@@ -323,7 +324,7 @@
      * @param array the array to use for initial elements
      * @return the ArrayData
      */
-    public static final ArrayData allocate(final int[] array) {
+    public static ArrayData allocate(final int[] array) {
          return new IntArrayData(array, array.length);
     }
 
@@ -333,7 +334,7 @@
      * @param array the array to use for initial elements
      * @return the ArrayData
      */
-    public static final ArrayData allocate(final long[] array) {
+    public static ArrayData allocate(final long[] array) {
         return new LongArrayData(array, array.length);
     }
 
@@ -343,7 +344,7 @@
      * @param array the array to use for initial elements
      * @return the ArrayData
      */
-    public static final ArrayData allocate(final double[] array) {
+    public static ArrayData allocate(final double[] array) {
         return new NumberArrayData(array, array.length);
     }
 
@@ -353,7 +354,7 @@
      * @param array the array to use for initial elements
      * @return the ArrayData
      */
-    public static final ArrayData allocate(final Object[] array) {
+    public static ArrayData allocate(final Object[] array) {
         return new ObjectArrayData(array, array.length);
     }
 
@@ -363,7 +364,7 @@
      * @param buf the nio ByteBuffer to wrap
      * @return the ArrayData
      */
-    public static final ArrayData allocate(final ByteBuffer buf) {
+    public static ArrayData allocate(final ByteBuffer buf) {
         return new ByteBufferArrayData(buf);
     }
 
@@ -373,7 +374,7 @@
      * @param underlying  the underlying ArrayData to wrap in the freeze filter
      * @return the frozen ArrayData
      */
-    public static final ArrayData freeze(final ArrayData underlying) {
+    public static ArrayData freeze(final ArrayData underlying) {
         return new FrozenArrayFilter(underlying);
     }
 
@@ -383,7 +384,7 @@
      * @param underlying  the underlying ArrayData to wrap in the seal filter
      * @return the sealed ArrayData
      */
-    public static final ArrayData seal(final ArrayData underlying) {
+    public static ArrayData seal(final ArrayData underlying) {
         return new SealedArrayFilter(underlying);
     }
 
@@ -393,7 +394,7 @@
      * @param  underlying the underlying ArrayData to wrap in the non extensible filter
      * @return new array data, filtered
      */
-    public static final ArrayData preventExtension(final ArrayData underlying) {
+    public static ArrayData preventExtension(final ArrayData underlying) {
         return new NonExtensibleArrayFilter(underlying);
     }
 
@@ -403,7 +404,7 @@
      * @param underlying the underlying ArrayDAta to wrap in the non extensible filter
      * @return new array data, filtered
      */
-    public static final ArrayData setIsLengthNotWritable(final ArrayData underlying) {
+    public static ArrayData setIsLengthNotWritable(final ArrayData underlying) {
         return new LengthNotWritableFilter(underlying);
     }
 
@@ -496,7 +497,9 @@
     public abstract ArrayData shiftRight(final int by);
 
     /**
-     * Ensure that the given index exists and won't fail subsequent
+     * Ensure that the given index exists and won't fail in a subsequent access.
+     * If {@code safeIndex} is equal or greater than the current length the length is
+     * updated to {@code safeIndex + 1}.
      *
      * @param safeIndex the index to ensure wont go out of bounds
      * @return new array data (or same)
@@ -673,19 +676,34 @@
     }
 
     /**
-     * Returns if element at specific index range can be deleted or not.
+     * Returns if element at specific index can be deleted or not.
      *
-     * @param fromIndex  the start index
-     * @param toIndex    the end index
+     * @param longIndex  the index
      * @param strict     are we in strict mode
      *
      * @return true if range can be deleted
      */
-    public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
+    public boolean canDelete(final long longIndex, final boolean strict) {
         return true;
     }
 
     /**
+     * Delete a range from the array if {@code fromIndex} is less than or equal to {@code toIndex}
+     * and the array supports deletion.
+     *
+     * @param fromIndex  the start index (inclusive)
+     * @param toIndex    the end index (inclusive)
+     * @param strict     are we in strict mode
+     * @return an array with the range deleted, or this array if no deletion took place
+     */
+    public final ArrayData safeDelete(final long fromIndex, final long toIndex, final boolean strict) {
+        if (fromIndex <= toIndex && canDelete(fromIndex, strict)) {
+            return delete(fromIndex, toIndex);
+        }
+        return this;
+    }
+
+    /**
      * Returns property descriptor for element at a given index
      *
      * @param global the global object
@@ -761,39 +779,6 @@
     }
 
     /**
-     * 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
diff --git a/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java
index 85f1b43..3c17d53 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java
@@ -164,7 +164,7 @@
     }
 
     @Override
-    public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
+    public boolean canDelete(final long longIndex, final boolean strict) {
         return false;
     }
 
diff --git a/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java
index 2fdd184..260dc8e 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java
@@ -57,7 +57,7 @@
     }
 
     /**
-     * Check if we can put one more element at the end of this continous
+     * Check if we can put one more element at the end of this continuous
      * array without reallocating, or if we are overwriting an already
      * allocated element
      *
@@ -191,7 +191,7 @@
 
     /**
      * Return element setter for a {@link ContinuousArrayData}
-     * @param clazz        clazz for exact type guard
+     * @param clazz        class for exact type guard
      * @param setHas       set has guard
      * @param elementType  element type
      * @return method handle for element setter
diff --git a/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java
index 381390c..0cba79f 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java
@@ -26,6 +26,7 @@
 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;
@@ -181,14 +182,13 @@
 
     @Override
     public ArrayData convert(final Class<?> type) {
-        if (type == Integer.class) {
+        if (type == Integer.class || type == Byte.class || type == Short.class) {
             return this;
         } else if (type == Long.class) {
             return convertToLong();
-        } else if (type == Double.class) {
+        } else if (type == Double.class || type == Float.class) {
             return convertToDouble();
         } else {
-            assert type == null || (!Number.class.isAssignableFrom(type) && !type.isPrimitive());
             return convertToObject();
         }
     }
@@ -220,7 +220,9 @@
             final int newLength = ArrayData.nextSize((int)safeIndex);
             array = Arrays.copyOf(array, newLength);
         }
-        setLength(safeIndex + 1);
+        if (safeIndex >= length()) {
+            setLength(safeIndex + 1);
+        }
         return this;
     }
 
@@ -343,17 +345,6 @@
     }
 
     @Override
-    public final ArrayData push(final boolean strict, final int item) {
-        final long      len     = length();
-        final ArrayData newData = ensure(len);
-        if (newData == this) {
-            array[(int)len] = item;
-            return this;
-        }
-        return newData.set((int)len, 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;
diff --git a/src/jdk/nashorn/internal/runtime/arrays/InvalidArrayIndexException.java b/src/jdk/nashorn/internal/runtime/arrays/InvalidArrayIndexException.java
deleted file mode 100644
index 170b65d..0000000
--- a/src/jdk/nashorn/internal/runtime/arrays/InvalidArrayIndexException.java
+++ /dev/null
@@ -1,66 +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.arrays;
-
-/**
- * Mechanism for communicating that something isn't a plain
- * numeric integer array index. This enables things like
- * array getters for the fast case in a try, basically
- * just consisting of an "array[index]" access without
- * any checks of boundary conditions that rarely happen
- */
-@SuppressWarnings("serial")
-class InvalidArrayIndexException extends Exception {
-
-    private final Object index;
-
-    InvalidArrayIndexException(final Object index) {
-        super(index == null ? "null" : index.toString());
-        this.index = index;
-    }
-
-    InvalidArrayIndexException(final int index) {
-        this(Integer.valueOf(index));
-    }
-
-    InvalidArrayIndexException(final long index) {
-        this(Long.valueOf(index));
-    }
-
-    InvalidArrayIndexException(final double index) {
-        this(Double.valueOf(index));
-    }
-
-    @Override
-    public String toString() {
-        return index.toString();
-    }
-
-    Object getIndex() {
-        return index;
-    }
-
-}
diff --git a/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java
index 0437cdf..544f883 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java
@@ -27,6 +27,7 @@
 
 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;
@@ -119,11 +120,11 @@
 
     @Override
     public ContinuousArrayData convert(final Class<?> type) {
-        if (type == Integer.class || type == Long.class) {
+        if (type == Integer.class || type == Long.class || type == Byte.class || type == Short.class) {
             return this;
         }
         final int len = (int)length();
-        if (type == Double.class) {
+        if (type == Double.class || type == Float.class) {
             return new NumberArrayData(toDoubleArray(), len);
         }
         return new ObjectArrayData(toObjectArray(false), len);
@@ -156,7 +157,9 @@
             final int newLength = ArrayData.nextSize((int)safeIndex);
             array = Arrays.copyOf(array, newLength);
         }
-        setLength(safeIndex + 1);
+        if (safeIndex >= length()) {
+            setLength(safeIndex + 1);
+        }
         return this;
     }
 
@@ -168,7 +171,8 @@
 
     @Override
     public ArrayData set(final int index, final Object value, final boolean strict) {
-        if (value instanceof Long || value instanceof Integer) {
+        if (value instanceof Long || value instanceof Integer ||
+            value instanceof Byte || value instanceof Short) {
             return set(index, ((Number)value).longValue(), strict);
         } else if (value == ScriptRuntime.UNDEFINED) {
             return new UndefinedArrayFilter(this).set(index, value, strict);
@@ -303,17 +307,6 @@
     }
 
     @Override
-    public final ArrayData push(final boolean strict, final long item) {
-        final long      len     = length();
-        final ArrayData newData = ensure(len);
-        if (newData == this) {
-            array[(int)len] = item;
-            return this;
-        }
-        return newData.set((int)len, 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;
diff --git a/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java
index 2522b97..0ff1af8 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java
@@ -28,6 +28,8 @@
 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 jdk.internal.dynalink.support.TypeUtilities;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.util.Arrays;
@@ -103,9 +105,14 @@
         return super.asArrayOfType(componentType);
     }
 
+    private static boolean canWiden(final Class<?> type) {
+        return TypeUtilities.isWrapperType(type) &&
+            type != Boolean.class && type != Character.class;
+    }
+
     @Override
     public ContinuousArrayData convert(final Class<?> type) {
-        if (type != Double.class && type != Integer.class && type != Long.class) {
+        if (! canWiden(type)) {
             final int len = (int)length();
             return new ObjectArrayData(toObjectArray(false), len);
         }
@@ -138,7 +145,9 @@
             final int newLength = ArrayData.nextSize((int)safeIndex);
             array = Arrays.copyOf(array, newLength); //todo fill with nan or never accessed?
         }
-        setLength(safeIndex + 1);
+        if (safeIndex >= length()) {
+            setLength(safeIndex + 1);
+        }
         return this;
 
     }
@@ -151,7 +160,7 @@
 
     @Override
     public ArrayData set(final int index, final Object value, final boolean strict) {
-        if (value instanceof Double || value instanceof Integer || value instanceof Long) {
+        if (value instanceof Double || (value != null && canWiden(value.getClass()))) {
             return set(index, ((Number)value).doubleValue(), strict);
         } else if (value == UNDEFINED) {
             return new UndefinedArrayFilter(this).set(index, value, strict);
@@ -277,17 +286,6 @@
     }
 
     @Override
-    public final ArrayData push(final boolean strict, final double item) {
-        final long      len     = length();
-        final ArrayData newData = ensure(len);
-        if (newData == this) {
-            array[(int)len] = item;
-            return this;
-        }
-        return newData.set((int)len, 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;
diff --git a/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java
index ebaa3d6..3ccf993 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java
@@ -123,7 +123,9 @@
             final int newLength = ArrayData.nextSize((int)safeIndex);
             array = Arrays.copyOf(array, newLength); //fill with undefined or OK? TODO
         }
-        setLength(safeIndex + 1);
+        if (safeIndex >= length()) {
+            setLength(safeIndex + 1);
+        }
         return this;
     }
 
diff --git a/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java b/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java
index 3e78f2d..67efe47 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java
@@ -50,15 +50,15 @@
 
     @Override
     public boolean canDelete(final int index, final boolean strict) {
-        if (strict) {
-            throw typeError("cant.delete.property", Integer.toString(index), "sealed array");
-        }
-        return false;
+        return canDelete(ArrayIndex.toLongIndex(index), strict);
     }
 
     @Override
-    public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
-        return canDelete((int) fromIndex, strict);
+    public boolean canDelete(final long longIndex, final boolean strict) {
+        if (strict) {
+            throw typeError("cant.delete.property", Long.toString(longIndex), "sealed array");
+        }
+        return false;
     }
 
     @Override
diff --git a/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java
index ff569d4..91ad425 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java
@@ -36,7 +36,7 @@
  * Handle arrays where the index is very large.
  */
 class SparseArrayData extends ArrayData {
-    static final int MAX_DENSE_LENGTH = 8 * 1024 * 1024;
+    static final int MAX_DENSE_LENGTH = 1024 * 1024;
 
     /** Underlying array. */
     private ArrayData underlying;
@@ -135,10 +135,17 @@
 
     @Override
     public ArrayData ensure(final long safeIndex) {
+        // Usually #ensure only needs to be called if safeIndex is greater or equal current length.
+        // SparseArrayData is an exception as an index smaller than our current length may still
+        // exceed the underlying ArrayData's capacity. Because of this, SparseArrayData invokes
+        // its ensure method internally in various places where other ArrayData subclasses don't,
+        // making it safe for outside uses to only call ensure(safeIndex) if safeIndex >= length.
         if (safeIndex < maxDenseLength && underlying.length() <= safeIndex) {
             underlying = underlying.ensure(safeIndex);
         }
-        setLength(Math.max(safeIndex + 1, length()));
+        if (safeIndex >= length()) {
+            setLength(safeIndex + 1);
+        }
         return this;
     }
 
@@ -159,8 +166,9 @@
     @Override
     public ArrayData set(final int index, final Object value, final boolean strict) {
         if (index >= 0 && index < maxDenseLength) {
+            final long oldLength = underlying.length();
             ensure(index);
-            underlying = underlying.set(index, value, strict);
+            underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict);
             setLength(Math.max(underlying.length(), length()));
         } else {
             final Long longIndex = indexToKey(index);
@@ -174,8 +182,9 @@
     @Override
     public ArrayData set(final int index, final int value, final boolean strict) {
         if (index >= 0 && index < maxDenseLength) {
+            final long oldLength = underlying.length();
             ensure(index);
-            underlying = underlying.set(index, value, strict);
+            underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict);
             setLength(Math.max(underlying.length(), length()));
         } else {
             final Long longIndex = indexToKey(index);
@@ -188,8 +197,9 @@
     @Override
     public ArrayData set(final int index, final long value, final boolean strict) {
         if (index >= 0 && index < maxDenseLength) {
+            final long oldLength = underlying.length();
             ensure(index);
-            underlying = underlying.set(index, value, strict);
+            underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict);
             setLength(Math.max(underlying.length(), length()));
         } else {
             final Long longIndex = indexToKey(index);
@@ -202,8 +212,9 @@
     @Override
     public ArrayData set(final int index, final double value, final boolean strict) {
         if (index >= 0 && index < maxDenseLength) {
+            final long oldLength = underlying.length();
             ensure(index);
-            underlying = underlying.set(index, value, strict);
+            underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict);
             setLength(Math.max(underlying.length(), length()));
         } else {
             final Long longIndex = indexToKey(index);
diff --git a/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java b/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java
index 40b3210..56b9157 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java
@@ -83,7 +83,7 @@
     }
 
     @Override
-    public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
+    public boolean canDelete(final long longIndex, final boolean strict) {
         return false;
     }
 
diff --git a/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java b/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java
index 9865dcb..e4f2a2c 100644
--- a/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java
+++ b/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java
@@ -34,7 +34,7 @@
  * This filter handles the presence of undefined array elements.
  */
 final class UndefinedArrayFilter extends ArrayFilter {
-    /** Bit vector tracking undefines. */
+    /** Bit vector tracking undefined slots. */
     private final BitVector undefined;
 
     UndefinedArrayFilter(final ArrayData underlying) {
diff --git a/src/jdk/nashorn/internal/runtime/linker/AdaptationException.java b/src/jdk/nashorn/internal/runtime/linker/AdaptationException.java
index 3bf3eec..aa29e99 100644
--- a/src/jdk/nashorn/internal/runtime/linker/AdaptationException.java
+++ b/src/jdk/nashorn/internal/runtime/linker/AdaptationException.java
@@ -30,6 +30,7 @@
     private final AdaptationResult adaptationResult;
 
     AdaptationException(final AdaptationResult.Outcome outcome, final String classList) {
+        super(null, null, false, false);
         this.adaptationResult = new AdaptationResult(outcome, classList);
     }
 
diff --git a/src/jdk/nashorn/internal/runtime/linker/AdaptationResult.java b/src/jdk/nashorn/internal/runtime/linker/AdaptationResult.java
index 52511e5..7aea9be 100644
--- a/src/jdk/nashorn/internal/runtime/linker/AdaptationResult.java
+++ b/src/jdk/nashorn/internal/runtime/linker/AdaptationResult.java
@@ -48,28 +48,25 @@
         ERROR_NO_ACCESSIBLE_CONSTRUCTOR,
         ERROR_MULTIPLE_SUPERCLASSES,
         ERROR_NO_COMMON_LOADER,
-        ERROR_FINAL_FINALIZER
+        ERROR_FINAL_FINALIZER,
+        ERROR_OTHER
     }
 
     static final AdaptationResult SUCCESSFUL_RESULT = new AdaptationResult(Outcome.SUCCESS, "");
 
     private final Outcome outcome;
-    private final String classList;
+    private final String[] messageArgs;
 
-    AdaptationResult(final Outcome outcome, final String classList) {
+    AdaptationResult(final Outcome outcome, final String... messageArgs) {
         this.outcome = outcome;
-        this.classList = classList;
+        this.messageArgs = messageArgs;
     }
 
     Outcome getOutcome() {
         return outcome;
     }
 
-    String getClassList() {
-        return classList;
-    }
-
     ECMAException typeError() {
-        return ECMAErrors.typeError("extend." + outcome, classList);
+        return ECMAErrors.typeError("extend." + outcome, messageArgs);
     }
 }
diff --git a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java
index cd4dd3b..1d0a166 100644
--- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java
+++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java
@@ -48,10 +48,8 @@
 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.objects.ScriptFunctionImpl;
 import jdk.nashorn.internal.runtime.ECMAException;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.OptimisticReturnFilters;
@@ -71,21 +69,20 @@
     private static final MethodHandle VOID_TO_OBJECT = MH.constant(Object.class, ScriptRuntime.UNDEFINED);
 
     /**
-     * The default dynalink relink threshold for megamorphisism is 8. In the case
+     * The default dynalink relink threshold for megamorphism 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.
+     * changes swapping out an entire property map and making a map guard fail.
+     * Since we need to set this value statically it must work with possibly changing
+     * optimistic types and dual fields settings. A higher value does not seem to have
+     * any other negative performance implication when running with object-only fields,
+     * so we choose a higher value here.
      *
      * 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;
+    private static final int NASHORN_DEFAULT_UNSTABLE_RELINK_THRESHOLD = 16;
 
     // do not create me!!
     private Bootstrap() {
@@ -119,6 +116,7 @@
                 return unboxReturnType(target, newType);
             }
         });
+        factory.setInternalObjectsFilter(NashornBeansLinker.createHiddenObjectFilter());
         final int relinkThreshold = Options.getIntProperty("nashorn.unstable.relink.threshold", NASHORN_DEFAULT_UNSTABLE_RELINK_THRESHOLD);
         if (relinkThreshold > -1) {
             factory.setUnstableRelinkThreshold(relinkThreshold);
@@ -191,7 +189,7 @@
      * @return true if the obj is an instance of @FunctionalInterface interface
      */
     public static boolean isFunctionalInterfaceObject(final Object obj) {
-        return !JSType.isPrimitive(obj) && (NashornBeansLinker.getFunctionalInterfaceMethod(obj.getClass()) != null);
+        return !JSType.isPrimitive(obj) && (NashornBeansLinker.getFunctionalInterfaceMethodName(obj.getClass()) != null);
     }
 
     /**
@@ -209,26 +207,13 @@
     }
 
     /**
-     * Bootstrapper for a specialized Runtime call
-     *
-     * @param lookup       lookup
-     * @param initialName  initial name for callsite
-     * @param type         method type for call site
-     *
-     * @return callsite for a runtime node
-     */
-    public static CallSite runtimeBootstrap(final MethodHandles.Lookup lookup, final String initialName, final MethodType type) {
-        return new RuntimeCallSite(type, initialName);
-    }
-
-    /**
      * 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
+     * @return callsite for a math intrinsic node
      */
     public static CallSite mathBootstrap(final MethodHandles.Lookup lookup, final String name, final MethodType type, final int programPoint) {
         final MethodHandle mh;
@@ -411,8 +396,8 @@
      * @throws ECMAException with {@code TypeError} if the object is not a callable.
      */
     public static Object bindCallable(final Object callable, final Object boundThis, final Object[] boundArgs) {
-        if (callable instanceof ScriptFunctionImpl) {
-            return ((ScriptFunctionImpl)callable).makeBoundFunction(boundThis, boundArgs);
+        if (callable instanceof ScriptFunction) {
+            return ((ScriptFunction)callable).createBound(boundThis, boundArgs);
         } else if (callable instanceof BoundCallable) {
             return ((BoundCallable)callable).bind(boundArgs);
         } else if (isCallable(callable)) {
diff --git a/src/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java b/src/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java
index d52063b..b871056 100644
--- a/src/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java
+++ b/src/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java
@@ -99,7 +99,7 @@
         MethodType newMethodType = descriptor.getMethodType().changeParameterType(0, callable.getClass());
         if (isCall) {
             // R(callable.class, T1, ...) => R(callable.class, boundThis.class, ...)
-            newMethodType = newMethodType.changeParameterType(1, boundThis.getClass());
+            newMethodType = newMethodType.changeParameterType(1, boundThis == null? Object.class : boundThis.getClass());
         }
         // R(callable.class[, boundThis.class], T2, ...) => R(callable.class[, boundThis.class], boundArg0.class, ..., boundArgn.class, T2, ...)
         for(int i = boundArgs.length; i-- > 0;) {
diff --git a/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java b/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java
index d2f23e8..3bc1149 100644
--- a/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java
+++ b/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java
@@ -25,11 +25,13 @@
 
 package jdk.nashorn.internal.runtime.linker;
 
+import static jdk.nashorn.internal.runtime.JSType.isString;
+import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_CALL;
 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_GETMEMBER;
 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_GETSLOT;
 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_SETMEMBER;
 import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_SETSLOT;
-import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_CALL;
+
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import jdk.internal.dynalink.CallSiteDescriptor;
@@ -97,9 +99,10 @@
             return null;
         }
 
-        final GuardedInvocation inv;
+        GuardedInvocation inv;
         if (jsObjectClass.isInstance(self)) {
             inv = lookup(desc, request, linkerServices);
+            inv = inv.replaceMethods(linkerServices.filterInternalObjects(inv.getInvocation()), inv.getGuard());
         } else {
             throw new AssertionError(); // Should never reach here.
         }
@@ -110,20 +113,21 @@
     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();
+        GuardedInvocation inv;
+        try {
+            inv = nashornBeansLinker.getGuardedInvocation(request, linkerServices);
+        } catch (Throwable th) {
+            inv = null;
+        }
 
         switch (operator) {
             case "getProp":
             case "getElem":
             case "getMethod":
-                if (c > 2) {
-                    return findGetMethod(desc);
-                }
-            // For indexed get, we want GuardedInvocation from beans linker and pass it.
-            // BrowserJSObjectLinker.get uses this fallback getter for explicit signature method access.
-            return findGetIndexMethod(nashornBeansLinker.getGuardedInvocation(request, linkerServices));
+                return c > 2? findGetMethod(desc, inv) : findGetIndexMethod(inv);
             case "setProp":
             case "setElem":
-                return c > 2 ? findSetMethod(desc) : findSetIndexMethod();
+                return c > 2? findSetMethod(desc, inv) : findSetIndexMethod();
             case "call":
                 return findCallMethod(desc);
             default:
@@ -131,7 +135,10 @@
         }
     }
 
-    private static GuardedInvocation findGetMethod(final CallSiteDescriptor desc) {
+    private static GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final GuardedInvocation inv) {
+        if (inv != null) {
+            return inv;
+        }
         final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
         final MethodHandle getter = MH.insertArguments(JSOBJECT_GETMEMBER, 1, name);
         return new GuardedInvocation(getter, IS_JSOBJECT_GUARD);
@@ -142,7 +149,10 @@
         return inv.replaceMethods(getter, inv.getGuard());
     }
 
-    private static GuardedInvocation findSetMethod(final CallSiteDescriptor desc) {
+    private static GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final GuardedInvocation inv) {
+        if (inv != null) {
+            return inv;
+        }
         final MethodHandle getter = MH.insertArguments(JSOBJECT_SETMEMBER, 1, desc.getNameToken(2));
         return new GuardedInvocation(getter, IS_JSOBJECT_GUARD);
     }
@@ -170,12 +180,12 @@
             if (index > -1) {
                 return JSOBJECT_GETSLOT.invokeExact(jsobj, index);
             }
-        } else if (key instanceof String) {
-            final String name = (String)key;
+        } else if (isString(key)) {
+            final String name = key.toString();
             if (name.indexOf('(') != -1) {
-                return fallback.invokeExact(jsobj, key);
+                return fallback.invokeExact(jsobj, (Object) name);
             }
-            return JSOBJECT_GETMEMBER.invokeExact(jsobj, (String)key);
+            return JSOBJECT_GETMEMBER.invokeExact(jsobj, name);
         }
         return null;
     }
@@ -186,8 +196,8 @@
             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);
+        } else if (isString(key)) {
+            JSOBJECT_SETMEMBER.invokeExact(jsobj, key.toString(), value);
         }
     }
 
diff --git a/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java b/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java
index aaf5a2c..8fd28cc 100644
--- a/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java
+++ b/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java
@@ -25,16 +25,14 @@
 
 package jdk.nashorn.internal.runtime.linker;
 
+import static jdk.nashorn.internal.runtime.JSType.isString;
+
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.util.HashMap;
 import java.util.Map;
 import javax.script.Bindings;
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.GuardedInvocation;
-import jdk.internal.dynalink.linker.GuardedTypeConversion;
-import jdk.internal.dynalink.linker.GuardingTypeConverterFactory;
 import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.internal.dynalink.linker.LinkerServices;
 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
@@ -48,7 +46,7 @@
  * A Dynalink linker to handle web browser built-in JS (DOM etc.) objects as well
  * as ScriptObjects from other Nashorn contexts.
  */
-final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTypeConverterFactory {
+final class JSObjectLinker implements TypeBasedGuardingDynamicLinker {
     private final NashornBeansLinker nashornBeansLinker;
 
     JSObjectLinker(final NashornBeansLinker nashornBeansLinker) {
@@ -79,9 +77,10 @@
             return null;
         }
 
-        final GuardedInvocation inv;
+        GuardedInvocation inv;
         if (self instanceof JSObject) {
             inv = lookup(desc, request, linkerServices);
+            inv = inv.replaceMethods(linkerServices.filterInternalObjects(inv.getInvocation()), inv.getGuard());
         } 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);
@@ -94,22 +93,6 @@
         return Bootstrap.asTypeSafeReturn(inv, linkerServices, desc);
     }
 
-    @Override
-    public GuardedTypeConversion convertToType(final Class<?> sourceType, final Class<?> targetType) throws Exception {
-        final boolean sourceIsAlwaysJSObject = JSObject.class.isAssignableFrom(sourceType);
-        if(!sourceIsAlwaysJSObject && !sourceType.isAssignableFrom(JSObject.class)) {
-            return null;
-        }
-
-        final MethodHandle converter = CONVERTERS.get(targetType);
-        if(converter == null) {
-            return null;
-        }
-
-        return new GuardedTypeConversion(new GuardedInvocation(converter, sourceIsAlwaysJSObject ? null : IS_JSOBJECT_GUARD).asType(MethodType.methodType(targetType, sourceType)), true);
-    }
-
-
     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();
@@ -185,11 +168,11 @@
             if (index > -1) {
                 return ((JSObject)jsobj).getSlot(index);
             }
-        } else if (key instanceof String) {
-            final String name = (String)key;
+        } else if (isString(key)) {
+            final String name = key.toString();
             // get with method name and signature. delegate it to beans linker!
             if (name.indexOf('(') != -1) {
-                return fallback.invokeExact(jsobj, key);
+                return fallback.invokeExact(jsobj, (Object) name);
             }
             return ((JSObject)jsobj).getMember(name);
         }
@@ -202,30 +185,11 @@
             ((JSObject)jsobj).setSlot((Integer)key, value);
         } else if (key instanceof Number) {
             ((JSObject)jsobj).setSlot(getIndex((Number)key), value);
-        } else if (key instanceof String) {
-            ((JSObject)jsobj).setMember((String)key, value);
+        } else if (isString(key)) {
+            ((JSObject)jsobj).setMember(key.toString(), value);
         }
     }
 
-    @SuppressWarnings("unused")
-    private static int toInt32(final JSObject obj) {
-        return JSType.toInt32(toNumber(obj));
-    }
-
-    @SuppressWarnings("unused")
-    private static long toLong(final JSObject obj) {
-        return JSType.toLong(toNumber(obj));
-    }
-
-    private static double toNumber(final JSObject obj) {
-        return obj == null ? 0 : obj.toNumber();
-    }
-
-    @SuppressWarnings("unused")
-    private static boolean toBoolean(final JSObject obj) {
-        return obj != null;
-    }
-
     private static int getIndex(final Number n) {
         final double value = n.doubleValue();
         return JSType.isRepresentableAsInt(value) ? (int)value : -1;
@@ -260,14 +224,6 @@
     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_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 findJSObjectMH_V(final String name, final Class<?> rtype, final Class<?>... types) {
         return MH.findVirtual(MethodHandles.lookup(), JSObject.class, name, MH.type(rtype, types));
     }
diff --git a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
index 7986b8b..4bc7b42 100644
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
@@ -106,7 +106,9 @@
  * <li>
  * If the adapter being generated can have class-level overrides, constructors taking same arguments as the superclass
  * constructors are created. These constructors simply delegate to the superclass constructor. They are simply used to
- * create instances of the adapter class, with no instance-level overrides, as they don't have them.
+ * create instances of the adapter class, with no instance-level overrides, as they don't have them. If the original
+ * class' constructor was variable arity, the adapter constructor will also be variable arity. Protected constructors
+ * are exposed as public.
  * </li>
  * </ul>
  * </p><p>
@@ -190,7 +192,6 @@
     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$";
@@ -202,6 +203,8 @@
 
     // This is the superclass for our generated adapter.
     private final Class<?> superClass;
+    // Interfaces implemented by our generated adapter.
+    private final List<Class<?>> interfaces;
     // Class loader used as the parent for the class loader we'll create to load the generated class. It will be a class
     // loader that has the visibility of all original types (class to extend and interfaces to implement) and of the
     // Nashorn classes.
@@ -253,6 +256,7 @@
         assert interfaces != null;
 
         this.superClass = superClass;
+        this.interfaces = interfaces;
         this.classOverride = classOverride;
         this.commonLoader = commonLoader;
         cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) {
@@ -494,7 +498,8 @@
         final Type[] argTypes = originalCtorType.getArgumentTypes();
 
         // All constructors must be public, even if in the superclass they were protected.
-        final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC, INIT,
+        final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC |
+                (ctor.isVarArgs() ? ACC_VARARGS : 0), INIT,
                 Type.getMethodDescriptor(originalCtorType.getReturnType(), argTypes), null, null));
 
         mv.visitCode();
@@ -543,7 +548,8 @@
         System.arraycopy(originalArgTypes, 0, newArgTypes, 0, argLen);
 
         // All constructors must be public, even if in the superclass they were protected.
-        // Existing super constructor <init>(this, args...) triggers generating <init>(this, scriptObj, args...).
+        // Existing super constructor <init>(this, args...) triggers generating <init>(this, args..., scriptObj).
+        // Any variable arity constructors become fixed-arity with explicit array arguments.
         final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC, INIT,
                 Type.getMethodDescriptor(originalCtorType.getReturnType(), newArgTypes), null, null));
 
@@ -568,7 +574,7 @@
             mv.visitVarInsn(ALOAD, 0);
             if (fromFunction && !mi.getName().equals(samName)) {
                 // Constructors initializing from a ScriptFunction only initialize methods with the SAM name.
-                // NOTE: if there's a concrete overloaded method sharing the SAM name, it'll be overriden too. This
+                // NOTE: if there's a concrete overloaded method sharing the SAM name, it'll be overridden too. This
                 // is a deliberate design choice. All other method handles are initialized to null.
                 mv.visitInsn(ACONST_NULL);
             } else {
@@ -593,7 +599,7 @@
         if (! fromFunction) {
             newArgTypes[argLen] = OBJECT_TYPE;
             final InstructionAdapter mv2 = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC, INIT,
-                Type.getMethodDescriptor(originalCtorType.getReturnType(), newArgTypes), null, null));
+                    Type.getMethodDescriptor(originalCtorType.getReturnType(), newArgTypes), null, null));
             generateOverridingConstructorWithObjectParam(mv2, ctor, originalCtorType.getDescriptor());
         }
     }
@@ -1028,6 +1034,24 @@
         endMethod(mv);
     }
 
+    // find the appropriate super type to use for invokespecial on the given interface
+    private Class<?> findInvokespecialOwnerFor(final Class<?> cl) {
+        assert Modifier.isInterface(cl.getModifiers()) : cl + " is not an interface";
+
+        if (cl.isAssignableFrom(superClass)) {
+            return superClass;
+        }
+
+        for (final Class<?> iface : interfaces) {
+             if (cl.isAssignableFrom(iface)) {
+                 return iface;
+             }
+        }
+
+        // we better that interface that extends the given interface!
+        throw new AssertionError("can't find the class/interface that extends " + cl);
+    }
+
     private void emitSuperCall(final InstructionAdapter mv, final Class<?> owner, final String name, final String methodDesc) {
         mv.visitVarInsn(ALOAD, 0);
         int nextParam = 1;
@@ -1039,7 +1063,9 @@
 
         // default method - non-abstract, interface method
         if (Modifier.isInterface(owner.getModifiers())) {
-            mv.invokespecial(Type.getInternalName(owner), name, methodDesc, false);
+            // we should call default method on the immediate "super" type - not on (possibly)
+            // the indirectly inherited interface class!
+            mv.invokespecial(Type.getInternalName(findInvokespecialOwnerFor(owner)), name, methodDesc, false);
         } else {
             mv.invokespecial(superClassName, name, methodDesc, false);
         }
diff --git a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
index 40ea01a..c6f653f 100644
--- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,23 +54,28 @@
 import jdk.nashorn.internal.runtime.ScriptObject;
 
 /**
- * <p>A factory class that generates adapter classes. Adapter classes allow implementation of Java interfaces and
- * extending of Java classes from JavaScript. For every combination of a superclass to extend and interfaces to
- * implement (collectively: "original types"), exactly one adapter class is generated that extends the specified
- * superclass and implements the specified interfaces. (But see the discussion of class-based overrides for exceptions.)
- * </p><p>
- * The adapter class is generated in a new secure class loader that inherits Nashorn's protection domain, and has either
- * one of the original types' class loader or the Nashorn's class loader as its parent - the parent class loader
- * is chosen so that all the original types and the Nashorn core classes are visible from it (as the adapter will have
- * constant pool references to ScriptObject and ScriptFunction classes). In case none of the candidate class loaders has
- * visibility of all the required types, an error is thrown. The class uses {@link JavaAdapterBytecodeGenerator} to
- * generate the adapter class itself; see its documentation for details about the generated class.
- * </p><p>
- * You normally don't use this class directly, but rather either create adapters from script using
- * {@link jdk.nashorn.internal.objects.NativeJava#extend(Object, Object...)}, using the {@code new} operator on abstract classes and interfaces (see
- * {@link jdk.nashorn.internal.objects.NativeJava#type(Object, Object)}), or implicitly when passing script functions to Java methods expecting SAM
- * types.
- * </p>
+ * A factory class that generates adapter classes. Adapter classes allow
+ * implementation of Java interfaces and extending of Java classes from
+ * JavaScript. For every combination of a superclass to extend and interfaces to
+ * implement (collectively: "original types"), exactly one adapter class is
+ * generated that extends the specified superclass and implements the specified
+ * interfaces. (But see the discussion of class-based overrides for exceptions.)
+ * <p>
+ * The adapter class is generated in a new secure class loader that inherits
+ * Nashorn's protection domain, and has either one of the original types' class
+ * loader or the Nashorn's class loader as its parent - the parent class loader
+ * is chosen so that all the original types and the Nashorn core classes are
+ * visible from it (as the adapter will have constant pool references to
+ * ScriptObject and ScriptFunction classes). In case none of the candidate class
+ * loaders has visibility of all the required types, an error is thrown. The
+ * class uses {@link JavaAdapterBytecodeGenerator} to generate the adapter class
+ * itself; see its documentation for details about the generated class.
+ * <p>
+ * You normally don't use this class directly, but rather either create adapters
+ * from script using {@link jdk.nashorn.internal.objects.NativeJava#extend(Object, Object...)},
+ * using the {@code new} operator on abstract classes and interfaces (see
+ * {@link jdk.nashorn.internal.objects.NativeJava#type(Object, Object)}), or
+ * implicitly when passing script functions to Java methods expecting SAM types.
  */
 
 @SuppressWarnings("javadoc")
@@ -93,25 +98,39 @@
     };
 
     /**
-     * Returns an adapter class for the specified original types. The adapter class extends/implements the original
-     * class/interfaces.
-     * @param types the original types. The caller must pass at least one Java type representing either a public
-     * interface or a non-final public class with at least one public or protected constructor. If more than one type is
-     * specified, at most one can be a class and the rest have to be interfaces. The class can be in any position in the
-     * array. Invoking the method twice with exactly the same types in the same order will return the same adapter
-     * class, any reordering of types or even addition or removal of redundant types (i.e. interfaces that other types
-     * in the list already implement/extend, or {@code java.lang.Object} in a list of types consisting purely of
-     * interfaces) will result in a different adapter class, even though those adapter classes are functionally
-     * identical; we deliberately don't want to incur the additional processing cost of canonicalizing type lists.
-     * @param classOverrides a JavaScript object with functions serving as the class-level overrides and
-     * implementations. These overrides are defined for all instances of the class, and can be further overridden on a
-     * per-instance basis by passing additional objects in the constructor.
-     * @param lookup the lookup object identifying the caller class. The generated adapter class will have the
-     * protection domain of the caller class iff the lookup object is full-strength, otherwise it will be completely
-     * unprivileged.
-     * @return an adapter class. See this class' documentation for details on the generated adapter class.
-     * @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.
+     * Returns an adapter class for the specified original types. The adapter
+     * class extends/implements the original class/interfaces.
+     *
+     * @param types the original types. The caller must pass at least one Java
+     *        type representing either a public interface or a non-final public
+     *        class with at least one public or protected constructor. If more
+     *        than one type is specified, at most one can be a class and the
+     *        rest have to be interfaces. The class can be in any position in
+     *        the array. Invoking the method twice with exactly the same types
+     *        in the same order will return the same adapter class, any
+     *        reordering of types or even addition or removal of redundant types
+     *        (i.e., interfaces that other types in the list already
+     *        implement/extend, or {@code java.lang.Object} in a list of types
+     *        consisting purely of interfaces) will result in a different
+     *        adapter class, even though those adapter classes are functionally
+     *        identical; we deliberately don't want to incur the additional
+     *        processing cost of canonicalizing type lists.
+     * @param classOverrides a JavaScript object with functions serving as the
+     *        class-level overrides and implementations. These overrides are
+     *        defined for all instances of the class, and can be further
+     *        overridden on a per-instance basis by passing additional objects
+     *        in the constructor.
+     * @param lookup the lookup object identifying the caller class. The
+     *        generated adapter class will have the protection domain of the
+     *        caller class iff the lookup object is full-strength, otherwise it
+     *        will be completely unprivileged.
+     *
+     * @return an adapter class. See this class' documentation for details on
+     *         the generated adapter class.
+     *
+     * @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, final ScriptObject classOverrides, final MethodHandles.Lookup lookup) {
         return getAdapterClassFor(types, classOverrides, getProtectionDomain(lookup));
@@ -148,15 +167,23 @@
     }
 
     /**
-     * Returns a method handle representing a constructor that takes a single argument of the source type (which,
-     * really, should be one of {@link ScriptObject}, {@link ScriptFunction}, or {@link Object}, and returns an instance
-     * of the adapter for the target type. Used to implement the function autoconverters as well as the Nashorn's
-     * JSR-223 script engine's {@code getInterface()} method.
-     * @param sourceType the source type; should be either {@link ScriptObject}, {@link ScriptFunction}, or
-     * {@link Object}. In case of {@code Object}, it will return a method handle that dispatches to either the script
-     * object or function constructor at invocation based on the actual argument.
+     * Returns a method handle representing a constructor that takes a single
+     * argument of the source type (which, really, should be one of {@link ScriptObject},
+     * {@link ScriptFunction}, or {@link Object}, and returns an instance of the
+     * adapter for the target type. Used to implement the function autoconverters
+     * as well as the Nashorn JSR-223 script engine's {@code getInterface()}
+     * method.
+     *
+     * @param sourceType the source type; should be either {@link ScriptObject},
+     *        {@link ScriptFunction}, or {@link Object}. In case of {@code Object},
+     *        it will return a method handle that dispatches to either the script
+     *        object or function constructor at invocation based on the actual
+     *        argument.
      * @param targetType the target type, for which adapter instances will be created
+     * @param lookup method handle lookup to use
+     *
      * @return the constructor method handle.
+     *
      * @throws Exception if anything goes wrong
      */
     public static MethodHandle getConstructor(final Class<?> sourceType, final Class<?> targetType, final MethodHandles.Lookup lookup) throws Exception {
@@ -168,13 +195,18 @@
     }
 
     /**
-     * Returns whether an instance of the specified class/interface can be generated from a ScriptFunction. Returns true
-     * iff: the adapter for the class/interface can be created, it is abstract (this includes interfaces), it has at
-     * least one abstract method, all the abstract methods share the same name, and it has a public or protected default
-     * constructor. Note that invoking this class will most likely result in the adapter class being defined in the JVM
-     * if it hasn't been already.
+     * Returns whether an instance of the specified class/interface can be
+     * generated from a ScriptFunction. Returns {@code true} iff: the adapter
+     * for the class/interface can be created, it is abstract (this includes
+     * interfaces), it has at least one abstract method, all the abstract
+     * methods share the same name, and it has a public or protected default
+     * constructor. Note that invoking this class will most likely result in the
+     * adapter class being defined in the JVM if it hasn't been already.
+     *
      * @param clazz the inspected class
-     * @return true iff an instance of the specified class/interface can be generated from a ScriptFunction.
+     *
+     * @return {@code true} iff an instance of the specified class/interface can
+     *         be generated from a ScriptFunction.
      */
     static boolean isAutoConvertibleFromFunction(final Class<?> clazz) {
         return getAdapterInfo(new Class<?>[] { clazz }).autoConvertibleFromFunction;
@@ -184,7 +216,7 @@
         final ClassAndLoader definingClassAndLoader = ClassAndLoader.getDefiningClassAndLoader(types);
 
         final Map<List<Class<?>>, AdapterInfo> adapterInfoMap = ADAPTER_INFO_MAPS.get(definingClassAndLoader.getRepresentativeClass());
-        final List<Class<?>> typeList = types.length == 1 ? getSingletonClassList(types[0]) : Arrays.asList(types.clone());
+        final List<Class<?>> typeList = types.length == 1 ? Collections.<Class<?>>singletonList(types[0]) : Arrays.asList(types.clone());
         AdapterInfo adapterInfo;
         synchronized(adapterInfoMap) {
             adapterInfo = adapterInfoMap.get(typeList);
@@ -196,14 +228,11 @@
         return adapterInfo;
     }
 
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    private static List<Class<?>> getSingletonClassList(final Class<?> clazz) {
-        return (List)Collections.singletonList(clazz);
-    }
-
    /**
      * For a given class, create its adapter class and associated info.
+     *
      * @param type the class for which the adapter is created
+     *
      * @return the adapter info for the class.
      */
     private static AdapterInfo createAdapterInfo(final Class<?>[] types, final ClassAndLoader definingClassAndLoader) {
@@ -241,6 +270,8 @@
                     return new AdapterInfo(effectiveSuperClass, interfaces, definingClassAndLoader);
                 } catch (final AdaptationException e) {
                     return new AdapterInfo(e.getAdaptationResult());
+                } catch (final RuntimeException e) {
+                    return new AdapterInfo(new AdaptationResult(AdaptationResult.Outcome.ERROR_OTHER, Arrays.toString(types), e.toString()));
                 }
             }
         }, CREATE_ADAPTER_INFO_ACC_CTXT);
@@ -314,11 +345,14 @@
         }
 
         /**
-         * Choose between the passed class loader and the class loader that defines the ScriptObject class, based on which
-         * of the two can see the classes in both.
-         * @param classAndLoader the loader and a representative class from it that will be used to add the generated
-         * adapter to its ADAPTER_INFO_MAPS.
+         * Choose between the passed class loader and the class loader that defines the
+         * ScriptObject class, based on which of the two can see the classes in both.
+         *
+         * @param classAndLoader the loader and a representative class from it that will
+         *        be used to add the generated adapter to its ADAPTER_INFO_MAPS.
+         *
          * @return the class loader that sees both the specified class and Nashorn classes.
+         *
          * @throws IllegalStateException if no such class loader is found.
          */
         private static ClassLoader findCommonLoader(final ClassAndLoader classAndLoader) throws AdaptationException {
diff --git a/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java b/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java
index 8b085e4..e165644 100644
--- a/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java
@@ -27,6 +27,7 @@
 
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import static jdk.nashorn.internal.runtime.JSType.isString;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
 import java.lang.invoke.MethodHandle;
@@ -78,7 +79,7 @@
         }
 
         if (obj == UNDEFINED) {
-            // NOTE: same reasoning for FindBugs NP_BOOLEAN_RETURN_NUL warning as in the preceding comment.
+            // NOTE: same reasoning for FindBugs NP_BOOLEAN_RETURN_NULL warning as in the preceding comment.
             return null;
         }
 
@@ -87,7 +88,7 @@
             return num != 0 && !Double.isNaN(num);
         }
 
-        if (obj instanceof String || obj instanceof ConsString) {
+        if (isString(obj)) {
             return ((CharSequence) obj).length() > 0;
         }
 
@@ -207,7 +208,7 @@
                 return f.longValue();
             } else if (obj instanceof Number) {
                 return ((Number)obj).longValue();
-            } else if (obj instanceof String || obj instanceof ConsString) {
+            } else if (isString(obj)) {
                 return JSType.toLong(obj);
             } else if (obj instanceof Boolean) {
                 return (Boolean)obj ? 1L : 0L;
diff --git a/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java b/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java
index 3c7fcb2..6cc2a1b 100644
--- a/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java
+++ b/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java
@@ -25,6 +25,8 @@
 
 package jdk.nashorn.internal.runtime.linker;
 
+import java.util.Objects;
+
 /**
  * Represents a an adapter for invoking superclass methods on an adapter instance generated by
  * {@code JavaAdapterBytecodeGenerator}. Note that objects of this class are just wrappers around the adapter instances,
@@ -34,8 +36,7 @@
     private final Object adapter;
 
     JavaSuperAdapter(final Object adapter) {
-        adapter.getClass(); // NPE check
-        this.adapter = adapter;
+        this.adapter = Objects.requireNonNull(adapter);
     }
 
     public Object getAdapter() {
diff --git a/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java b/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java
index 46324db..10dbf01 100644
--- a/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java
+++ b/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java
@@ -43,6 +43,7 @@
 import java.util.Random;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.LongAdder;
 import jdk.internal.dynalink.ChainedCallSite;
 import jdk.internal.dynalink.DynamicLinker;
 import jdk.internal.dynalink.linker.GuardedInvocation;
@@ -70,7 +71,7 @@
     LinkerCallSite(final NashornCallSiteDescriptor descriptor) {
         super(descriptor);
         if (Context.DEBUG) {
-            LinkerCallSite.count++;
+            LinkerCallSite.count.increment();
         }
     }
 
@@ -173,7 +174,7 @@
      * @return self reference
      */
     public static Object increaseMissCount(final String desc, final Object self) {
-        ++missCount;
+        missCount.increment();
         if (r.nextInt(100) < missSamplingPercentage) {
             final AtomicInteger i = missCounts.get(desc);
             if (i == null) {
@@ -500,7 +501,7 @@
          * @param desc callsite descriptor string
          * @param args arguments to function
          *
-         * @throws Throwable if invocation failes or throws exception/error
+         * @throws Throwable if invocation fails or throws exception/error
          */
         @SuppressWarnings("unused")
         public void traceMiss(final String desc, final Object... args) throws Throwable {
@@ -509,12 +510,19 @@
     }
 
     // counters updated in debug mode
-    private static int count;
+    private static LongAdder count;
     private static final HashMap<String, AtomicInteger> missCounts = new HashMap<>();
-    private static int missCount;
+    private static LongAdder missCount;
     private static final Random r = new Random();
     private static final int missSamplingPercentage = Options.getIntProperty("nashorn.tcs.miss.samplePercent", 1);
 
+    static {
+        if (Context.DEBUG) {
+            count = new LongAdder();
+            missCount = new LongAdder();
+        }
+    }
+
     @Override
     protected int getMaxChainLength() {
         return 8;
@@ -524,16 +532,16 @@
      * Get the callsite count
      * @return the count
      */
-    public static int getCount() {
-        return count;
+    public static long getCount() {
+        return count.longValue();
     }
 
     /**
      * Get the callsite miss count
      * @return the missCount
      */
-    public static int getMissCount() {
-        return missCount;
+    public static long getMissCount() {
+        return missCount.longValue();
     }
 
     /**
diff --git a/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java b/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java
index da12af2..6b7bce3 100644
--- a/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java
@@ -26,7 +26,6 @@
 package jdk.nashorn.internal.runtime.linker;
 
 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;
@@ -40,22 +39,25 @@
 import jdk.internal.dynalink.linker.GuardingDynamicLinker;
 import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.internal.dynalink.linker.LinkerServices;
-import jdk.internal.dynalink.support.Guards;
+import jdk.internal.dynalink.linker.MethodHandleTransformer;
+import jdk.internal.dynalink.support.DefaultInternalObjectFilter;
 import jdk.internal.dynalink.support.Lookup;
 import jdk.nashorn.api.scripting.ScriptUtils;
-import jdk.nashorn.internal.objects.NativeArray;
 import jdk.nashorn.internal.runtime.ConsString;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ScriptObject;
-import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.options.Options;
 
 /**
  * This linker delegates to a {@code BeansLinker} but passes it a special linker services object that has a modified
- * {@code asType} method that will ensure that we never pass internal engine objects that should not be externally
- * observable (currently ConsString and ScriptObject) to Java APIs, but rather that we flatten it into a String. We can't just add
- * this functionality as custom converters via {@code GuaardingTypeConverterFactory}, since they are not consulted when
- * the target method handle parameter signature is {@code Object}.
+ * {@code compareConversion} method that favors conversion of {@link ConsString} to either {@link String} or
+ * {@link CharSequence}. It also provides a {@link #createHiddenObjectFilter()} method for use with bootstrap that will
+ * ensure that we never pass internal engine objects that should not be externally observable (currently ConsString and
+ * ScriptObject) to Java APIs, but rather that we flatten it into a String. We can't just add this functionality as
+ * custom converters via {@code GuaardingTypeConverterFactory}, since they are not consulted when
+ * the target method handle parameter signature is {@code Object}. This linker also makes sure that primitive
+ * {@link String} operations can be invoked on a {@link ConsString}, and allows invocation of objects implementing
+ * the {@link FunctionalInterface} attribute.
  */
 public class NashornBeansLinker implements GuardingDynamicLinker {
     // System property to control whether to wrap ScriptObject->ScriptObjectMirror for
@@ -63,25 +65,21 @@
     private static final boolean MIRROR_ALWAYS = Options.getBooleanProperty("nashorn.mirror.always", true);
 
     private static final MethodHandle EXPORT_ARGUMENT;
-    private static final MethodHandle EXPORT_NATIVE_ARRAY;
-    private static final MethodHandle EXPORT_SCRIPT_OBJECT;
     private static final MethodHandle IMPORT_RESULT;
     private static final MethodHandle FILTER_CONSSTRING;
 
     static {
         final Lookup lookup  = new Lookup(MethodHandles.lookup());
         EXPORT_ARGUMENT      = lookup.findOwnStatic("exportArgument", Object.class, Object.class);
-        EXPORT_NATIVE_ARRAY  = lookup.findOwnStatic("exportNativeArray", Object.class, NativeArray.class);
-        EXPORT_SCRIPT_OBJECT = lookup.findOwnStatic("exportScriptObject", Object.class, ScriptObject.class);
         IMPORT_RESULT        = lookup.findOwnStatic("importResult", Object.class, Object.class);
         FILTER_CONSSTRING    = lookup.findOwnStatic("consStringFilter", Object.class, Object.class);
     }
 
     // cache of @FunctionalInterface method of implementor classes
-    private static final ClassValue<Method> FUNCTIONAL_IFACE_METHOD = new ClassValue<Method>() {
+    private static final ClassValue<String> FUNCTIONAL_IFACE_METHOD_NAME = new ClassValue<String>() {
         @Override
-        protected Method computeValue(final Class<?> type) {
-            return findFunctionalInterfaceMethod(type);
+        protected String computeValue(final Class<?> type) {
+            return findFunctionalInterfaceMethodName(type);
         }
     };
 
@@ -106,18 +104,21 @@
             // annotated interface. This way Java method, constructor references or
             // implementations of java.util.function.* interfaces can be called as though
             // those are script functions.
-            final Method m = getFunctionalInterfaceMethod(self.getClass());
-            if (m != null) {
+            final String name = getFunctionalInterfaceMethodName(self.getClass());
+            if (name != null) {
                 final MethodType callType = desc.getMethodType();
-                // 'callee' and 'thiz' passed from script + actual arguments
-                if (callType.parameterCount() != m.getParameterCount() + 2) {
-                    throw typeError("no.method.matches.args", ScriptRuntime.safeToString(self));
-                }
-                return new GuardedInvocation(
-                        // drop 'thiz' passed from the script.
-                        MH.dropArguments(desc.getLookup().unreflect(m), 1, callType.parameterType(1)),
-                        Guards.getInstanceOfGuard(m.getDeclaringClass())).asTypeSafeReturn(
-                                new NashornBeansLinkerServices(linkerServices), callType);
+                // drop callee (Undefined ScriptFunction) and change the request to be dyn:callMethod:<name>
+                final NashornCallSiteDescriptor newDesc = NashornCallSiteDescriptor.get(desc.getLookup(),
+                        "dyn:callMethod:" + name, desc.getMethodType().dropParameterTypes(1, 2),
+                        NashornCallSiteDescriptor.getFlags(desc));
+                final GuardedInvocation gi = getGuardedInvocation(beansLinker,
+                        linkRequest.replaceArguments(newDesc, linkRequest.getArguments()),
+                        new NashornBeansLinkerServices(linkerServices));
+
+                // drop 'thiz' passed from the script.
+                return gi.replaceMethods(
+                    MH.dropArguments(linkerServices.filterInternalObjects(gi.getInvocation()), 1, callType.parameterType(1)),
+                    gi.getGuard());
             }
         }
         return getGuardedInvocation(beansLinker, linkRequest, linkerServices);
@@ -141,21 +142,6 @@
         return exportArgument(arg, MIRROR_ALWAYS);
     }
 
-    @SuppressWarnings("unused")
-    private static Object exportNativeArray(final NativeArray arg) {
-        return exportArgument(arg, MIRROR_ALWAYS);
-    }
-
-    @SuppressWarnings("unused")
-    private static Object exportScriptObject(final ScriptObject arg) {
-        return exportArgument(arg, MIRROR_ALWAYS);
-    }
-
-    @SuppressWarnings("unused")
-    private static Object exportScriptArray(final NativeArray arg) {
-        return exportArgument(arg, MIRROR_ALWAYS);
-    }
-
     static Object exportArgument(final Object arg, final boolean mirrorAlways) {
         if (arg instanceof ConsString) {
             return arg.toString();
@@ -176,13 +162,13 @@
         return arg instanceof ConsString ? arg.toString() : arg;
     }
 
-    private static Method findFunctionalInterfaceMethod(final Class<?> clazz) {
+    private static String findFunctionalInterfaceMethodName(final Class<?> clazz) {
         if (clazz == null) {
             return null;
         }
 
         for (final Class<?> iface : clazz.getInterfaces()) {
-            // check accessiblity up-front
+            // check accessibility up-front
             if (! Context.isAccessibleClass(iface)) {
                 continue;
             }
@@ -192,20 +178,24 @@
                 // return the first abstract method
                 for (final Method m : iface.getMethods()) {
                     if (Modifier.isAbstract(m.getModifiers())) {
-                        return m;
+                        return m.getName();
                     }
                 }
             }
         }
 
         // did not find here, try super class
-        return findFunctionalInterfaceMethod(clazz.getSuperclass());
+        return findFunctionalInterfaceMethodName(clazz.getSuperclass());
     }
 
     // Returns @FunctionalInterface annotated interface's single abstract
-    // method. If not found, returns null.
-    static Method getFunctionalInterfaceMethod(final Class<?> clazz) {
-        return FUNCTIONAL_IFACE_METHOD.get(clazz);
+    // method name. If not found, returns null.
+    static String getFunctionalInterfaceMethodName(final Class<?> clazz) {
+        return FUNCTIONAL_IFACE_METHOD_NAME.get(clazz);
+    }
+
+    static MethodHandleTransformer createHiddenObjectFilter() {
+        return new DefaultInternalObjectFilter(EXPORT_ARGUMENT, MIRROR_ALWAYS ? IMPORT_RESULT : null);
     }
 
     private static class NashornBeansLinkerServices implements LinkerServices {
@@ -217,50 +207,7 @@
 
         @Override
         public MethodHandle asType(final MethodHandle handle, final MethodType fromType) {
-            final MethodType handleType = handle.type();
-            final int paramCount = handleType.parameterCount();
-            assert fromType.parameterCount() == handleType.parameterCount();
-
-            MethodType newFromType = fromType;
-            MethodHandle[] filters = null;
-            for(int i = 0; i < paramCount; ++i) {
-                final MethodHandle filter = argConversionFilter(handleType.parameterType(i), fromType.parameterType(i));
-                if (filter != null) {
-                    if (filters == null) {
-                        filters = new MethodHandle[paramCount];
-                    }
-                    // "erase" specific type with Object type or else we'll get filter mismatch
-                    newFromType = newFromType.changeParameterType(i, Object.class);
-                    filters[i] = filter;
-                }
-            }
-
-            final MethodHandle typed = linkerServices.asType(handle, newFromType);
-            MethodHandle result = filters != null ? MethodHandles.filterArguments(typed, 0, filters) : typed;
-            // Filter Object typed return value for possible ScriptObjectMirror. We convert
-            // ScriptObjectMirror as ScriptObject (if it is mirror from current global).
-            if (MIRROR_ALWAYS && areBothObjects(handleType.returnType(), fromType.returnType())) {
-                result = MethodHandles.filterReturnValue(result, IMPORT_RESULT);
-            }
-
-            return result;
-        }
-
-        private static MethodHandle argConversionFilter(final Class<?> handleType, final Class<?> fromType) {
-            if (handleType == Object.class) {
-                if (fromType == Object.class) {
-                    return EXPORT_ARGUMENT;
-                } else if (fromType == NativeArray.class) {
-                    return EXPORT_NATIVE_ARRAY;
-                } else if (fromType == ScriptObject.class) {
-                    return EXPORT_SCRIPT_OBJECT;
-                }
-            }
-            return null;
-        }
-
-        private static boolean areBothObjects(final Class<?> handleType, final Class<?> fromType) {
-            return handleType == Object.class && fromType == Object.class;
+            return linkerServices.asType(handle, fromType);
         }
 
         @Override
@@ -296,5 +243,10 @@
             }
             return linkerServices.compareConversion(sourceType, targetType1, targetType2);
         }
+
+        @Override
+        public MethodHandle filterInternalObjects(final MethodHandle target) {
+            return linkerServices.filterInternalObjects(target);
+        }
     }
 }
diff --git a/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java b/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java
index 2cbbf06..aade455 100644
--- a/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java
@@ -27,6 +27,8 @@
 
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import static jdk.nashorn.internal.runtime.JSType.GET_UNDEFINED;
+import static jdk.nashorn.internal.runtime.JSType.TYPE_OBJECT_INDEX;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
 import java.lang.invoke.MethodHandle;
@@ -86,10 +88,13 @@
         final String operator = desc.getFirstOperator();
         switch (operator) {
         case "new":
+            if(BeansLinker.isDynamicConstructor(self)) {
+                throw typeError("no.constructor.matches.args", ScriptRuntime.safeToString(self));
+            }
             if(BeansLinker.isDynamicMethod(self)) {
                 throw typeError("method.not.constructor", ScriptRuntime.safeToString(self));
             }
-            throw typeError("not.a.function", ScriptRuntime.safeToString(self));
+            throw typeError("not.a.function", desc.getFunctionErrorMessage(self));
         case "call":
             if(BeansLinker.isDynamicConstructor(self)) {
                 throw typeError("constructor.requires.new", ScriptRuntime.safeToString(self));
@@ -97,10 +102,12 @@
             if(BeansLinker.isDynamicMethod(self)) {
                 throw typeError("no.method.matches.args", ScriptRuntime.safeToString(self));
             }
-            throw typeError("not.a.function", ScriptRuntime.safeToString(self));
+            throw typeError("not.a.function", desc.getFunctionErrorMessage(self));
         case "callMethod":
-        case "getMethod":
             throw typeError("no.such.function", getArgument(linkRequest), ScriptRuntime.safeToString(self));
+        case "getMethod":
+            // evaluate to undefined, later on Undefined will take care of throwing TypeError
+            return getInvocation(MH.dropArguments(GET_UNDEFINED.get(TYPE_OBJECT_INDEX), 0, Object.class), self, linkerServices, desc);
         case "getProp":
         case "getElem":
             if(NashornCallSiteDescriptor.isOptimistic(desc)) {
diff --git a/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java b/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java
index 27fc3a2..cc654dc 100644
--- a/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java
@@ -34,6 +34,7 @@
 import jdk.internal.dynalink.support.AbstractCallSiteDescriptor;
 import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
 import jdk.nashorn.internal.ir.debug.NashornTextifier;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
 
 /**
  * Nashorn-specific implementation of Dynalink's {@link CallSiteDescriptor}. The reason we have our own subclass is that
@@ -150,7 +151,7 @@
     public static NashornCallSiteDescriptor get(final MethodHandles.Lookup lookup, final String name,
             final MethodType methodType, final int flags) {
         final String[] tokenizedName = CallSiteDescriptorFactory.tokenizeName(name);
-        assert tokenizedName.length == 2 || tokenizedName.length == 3;
+        assert tokenizedName.length >= 2;
         assert "dyn".equals(tokenizedName[0]);
         assert tokenizedName[1] != null;
         // TODO: see if we can move mangling/unmangling into Dynalink
@@ -248,6 +249,54 @@
     }
 
     /**
+     * If this is a dyn:call or dyn:new, this returns function description from callsite.
+     * Caller has to make sure this is a dyn:call or dyn:new call site.
+     *
+     * @return function description if available (or null)
+     */
+    public String getFunctionDescription() {
+        assert getFirstOperator().equals("call") || getFirstOperator().equals("new");
+        return getNameTokenCount() > 2? getNameToken(2) : null;
+    }
+
+    /**
+     * If this is a dyn:call or dyn:new, this returns function description from callsite.
+     * Caller has to make sure this is a dyn:call or dyn:new call site.
+     *
+     * @param desc call site descriptor
+     * @return function description if available (or null)
+     */
+    public static String getFunctionDescription(final CallSiteDescriptor desc) {
+        return desc instanceof NashornCallSiteDescriptor ?
+                ((NashornCallSiteDescriptor)desc).getFunctionDescription() : null;
+    }
+
+
+    /**
+     * Returns the error message to be used when dyn:call or dyn:new is used on a non-function.
+     *
+     * @param obj object on which dyn:call or dyn:new is used
+     * @return error message
+     */
+    public String getFunctionErrorMessage(final Object obj) {
+        final String funcDesc = getFunctionDescription();
+        return funcDesc != null? funcDesc : ScriptRuntime.safeToString(obj);
+    }
+
+    /**
+     * Returns the error message to be used when dyn:call or dyn:new is used on a non-function.
+     *
+     * @param desc call site descriptor
+     * @param obj object on which dyn:call or dyn:new is used
+     * @return error message
+     */
+    public static String getFunctionErrorMessage(final CallSiteDescriptor desc, final Object obj) {
+        return desc instanceof NashornCallSiteDescriptor ?
+                ((NashornCallSiteDescriptor)desc).getFunctionErrorMessage(obj) :
+                ScriptRuntime.safeToString(obj);
+    }
+
+    /**
      * Returns the Nashorn-specific flags for this call site descriptor.
      * @param desc the descriptor. It can be any kind of a call site descriptor, not necessarily a
      * {@code NashornCallSiteDescriptor}. This allows for graceful interoperability when linking Nashorn with code
@@ -274,7 +323,7 @@
      * {@code NashornCallSiteDescriptor}. This allows for graceful interoperability when linking Nashorn with code
      * generated outside of Nashorn.
      * @param flag the tested flag
-     * @return true if the flag is set, false otherwise (it will be false if the decriptor is not a Nashorn call site
+     * @return true if the flag is set, false otherwise (it will be false if the descriptor is not a Nashorn call site
      * descriptor).
      */
     private static boolean isFlag(final CallSiteDescriptor desc, final int flag) {
diff --git a/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java b/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java
index dac36d4..ca7034d 100644
--- a/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java
@@ -33,7 +33,6 @@
 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;
 import jdk.nashorn.internal.runtime.Property;
 import jdk.nashorn.internal.runtime.PropertyMap;
@@ -123,7 +122,7 @@
      */
     static boolean needsGuard(final Property property, final CallSiteDescriptor desc) {
         return property == null || property.isConfigurable()
-                || property.isBound() || !ObjectClassGenerator.OBJECT_FIELDS_ONLY
+                || property.isBound() || property.hasDualFields()
                 || !NashornCallSiteDescriptor.isFastScope(desc) || property.canChangeType();
     }
 
diff --git a/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java b/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java
index 75af367..ddcbae1 100644
--- a/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java
@@ -29,13 +29,15 @@
 
 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.Modifier;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.Collection;
 import java.util.Deque;
 import java.util.List;
 import java.util.Map;
+import java.util.Queue;
 import javax.script.Bindings;
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.ConversionComparator;
@@ -47,11 +49,13 @@
 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
 import jdk.internal.dynalink.support.Guards;
 import jdk.internal.dynalink.support.LinkerServicesImpl;
+import jdk.internal.dynalink.support.Lookup;
 import jdk.nashorn.api.scripting.JSObject;
 import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import jdk.nashorn.api.scripting.ScriptUtils;
 import jdk.nashorn.internal.objects.NativeArray;
 import jdk.nashorn.internal.runtime.JSType;
+import jdk.nashorn.internal.runtime.ListAdapter;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.Undefined;
@@ -167,7 +171,7 @@
         return null;
     }
 
-    private static Lookup getCurrentLookup() {
+    private static java.lang.invoke.MethodHandles.Lookup getCurrentLookup() {
         final LinkRequest currentRequest = AccessController.doPrivileged(new PrivilegedAction<LinkRequest>() {
             @Override
             public LinkRequest run() {
@@ -179,12 +183,12 @@
 
     /**
      * Returns a guarded invocation that converts from a source type that is NativeArray to a Java array or List or
-     * Deque type.
+     * Queue or Deque or Collection type.
      * @param sourceType the source type (presumably NativeArray a superclass of it)
-     * @param targetType the target type (presumably an array type, or List or Deque)
+     * @param targetType the target type (presumably an array type, or List or Queue, or Deque, or Collection)
      * @return a guarded invocation that converts from the source type to the target type. null is returned if
      * either the source type is neither NativeArray, nor a superclass of it, or if the target type is not an array
-     * type, List, or Deque.
+     * type, List, Queue, Deque, or Collection.
      */
     private static GuardedInvocation getArrayConverter(final Class<?> sourceType, final Class<?> targetType) {
         final boolean isSourceTypeNativeArray = sourceType == NativeArray.class;
@@ -195,12 +199,14 @@
             final MethodHandle guard = isSourceTypeGeneric ? IS_NATIVE_ARRAY : null;
             if(targetType.isArray()) {
                 return new GuardedInvocation(ARRAY_CONVERTERS.get(targetType), guard);
-            }
-            if(targetType == List.class) {
-                return new GuardedInvocation(JSType.TO_JAVA_LIST.methodHandle(), guard);
-            }
-            if(targetType == Deque.class) {
-                return new GuardedInvocation(JSType.TO_JAVA_DEQUE.methodHandle(), guard);
+            } else if(targetType == List.class) {
+                return new GuardedInvocation(TO_LIST, guard);
+            } else if(targetType == Deque.class) {
+                return new GuardedInvocation(TO_DEQUE, guard);
+            } else if(targetType == Queue.class) {
+                return new GuardedInvocation(TO_QUEUE, guard);
+            } else if(targetType == Collection.class) {
+                return new GuardedInvocation(TO_COLLECTION, guard);
             }
         }
         return null;
@@ -216,10 +222,11 @@
         // 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)) {
+            if (ScriptObject.class.isAssignableFrom(sourceType)) {
                 return new GuardedInvocation(CREATE_MIRROR);
+            } else if (sourceType.isAssignableFrom(ScriptObject.class) || sourceType.isInterface()) {
+                return new GuardedInvocation(CREATE_MIRROR, IS_SCRIPT_OBJECT);
             }
-            return new GuardedInvocation(CREATE_MIRROR, IS_SCRIPT_OBJECT);
         }
         return null;
     }
@@ -285,6 +292,23 @@
     private static final MethodHandle IS_NASHORN_OR_UNDEFINED_TYPE = findOwnMH("isNashornTypeOrUndefined", Boolean.TYPE, Object.class);
     private static final MethodHandle CREATE_MIRROR = findOwnMH("createMirror", Object.class, Object.class);
 
+    private static final MethodHandle TO_COLLECTION;
+    private static final MethodHandle TO_DEQUE;
+    private static final MethodHandle TO_LIST;
+    private static final MethodHandle TO_QUEUE;
+    static {
+        final MethodHandle listAdapterCreate = new Lookup(MethodHandles.lookup()).findStatic(
+                ListAdapter.class, "create", MethodType.methodType(ListAdapter.class, Object.class));
+        TO_COLLECTION = asReturning(listAdapterCreate, Collection.class);
+        TO_DEQUE = asReturning(listAdapterCreate, Deque.class);
+        TO_LIST = asReturning(listAdapterCreate, List.class);
+        TO_QUEUE = asReturning(listAdapterCreate, Queue.class);
+    }
+
+    private static MethodHandle asReturning(final MethodHandle mh, final Class<?> nrtype) {
+        return mh.asType(mh.type().changeReturnType(nrtype));
+    }
+
     @SuppressWarnings("unused")
     private static boolean isNashornTypeOrUndefined(final Object obj) {
         return obj instanceof ScriptObject || obj instanceof Undefined;
diff --git a/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java b/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java
index e8b8c43..4de5262 100644
--- a/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java
+++ b/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java
@@ -39,6 +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.JSType;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 
 /**
@@ -170,7 +171,7 @@
 
     @SuppressWarnings("unused")
     private static boolean isJavaScriptPrimitive(final Object o) {
-        return o instanceof String || o instanceof Boolean || o instanceof Number || o instanceof ConsString || o == null;
+        return JSType.isString(o) || o instanceof Boolean || o instanceof Number || o == null;
     }
 
     private static final MethodHandle GUARD_PRIMITIVE = findOwnMH("isJavaScriptPrimitive", boolean.class, Object.class);
diff --git a/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java b/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java
index 2a536bb..6c2f885 100644
--- a/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java
+++ b/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java
@@ -26,17 +26,23 @@
 package jdk.nashorn.internal.runtime.linker;
 
 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 java.lang.invoke.SwitchPoint;
 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.internal.dynalink.support.Guards;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.FindProperty;
 import jdk.nashorn.internal.runtime.GlobalConstants;
+import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.UserAccessorProperty;
 
 /**
@@ -46,6 +52,11 @@
  */
 public final class PrimitiveLookup {
 
+    /** Method handle to link setters on primitive base. See ES5 8.7.2. */
+    private static final MethodHandle PRIMITIVE_SETTER = findOwnMH("primitiveSetter",
+            MH.type(void.class, ScriptObject.class, Object.class, Object.class, boolean.class, Object.class));
+
+
     private PrimitiveLookup() {
     }
 
@@ -87,40 +98,58 @@
                                                     final ScriptObject wrappedReceiver, final MethodHandle wrapFilter,
                                                     final MethodHandle protoFilter) {
         final CallSiteDescriptor desc = request.getCallSiteDescriptor();
+        final String name;
+        final FindProperty find;
 
-        //checks whether the property name is hard-coded in the call-site (i.e. a getProp vs a getElem, or setProp vs setElem)
-        //if it is we can make assumptions on the property: that if it is not defined on primitive wrapper itself it never will be.
-        //so in that case we can skip creation of primitive wrapper and start our search with the prototype.
         if (desc.getNameTokenCount() > 2) {
-            final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
-            final FindProperty find = wrappedReceiver.findProperty(name, true);
+            name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+            find = wrappedReceiver.findProperty(name, true);
+        } else {
+            name = null;
+            find = null;
+        }
 
-            if (find == null) {
-                // Give up early, give chance to BeanLinker and NashornBottomLinker to deal with it.
-                return null;
-            }
+        final String firstOp = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0);
 
-            final SwitchPoint sp = find.getProperty().getBuiltinSwitchPoint(); //can use this instead of proto filter
-            if (sp instanceof Context.BuiltinSwitchPoint && !sp.hasBeenInvalidated()) {
-                return new GuardedInvocation(GlobalConstants.staticConstantGetter(find.getObjectValue()), guard, sp, null);
-            }
+        switch (firstOp) {
+        case "getProp":
+        case "getElem":
+        case "getMethod":
+            //checks whether the property name is hard-coded in the call-site (i.e. a getProp vs a getElem, or setProp vs setElem)
+            //if it is we can make assumptions on the property: that if it is not defined on primitive wrapper itself it never will be.
+            //so in that case we can skip creation of primitive wrapper and start our search with the prototype.
+            if (name != null) {
+                if (find == null) {
+                    // Give up early, give chance to BeanLinker and NashornBottomLinker to deal with it.
+                    return null;
+                }
 
-            if (find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) {
-                // If property is found in the prototype object bind the method handle directly to
-                // the proto filter instead of going through wrapper instantiation below.
-                final ScriptObject proto = wrappedReceiver.getProto();
-                final GuardedInvocation link = proto.lookup(desc, request);
+                final SwitchPoint sp = find.getProperty().getBuiltinSwitchPoint(); //can use this instead of proto filter
+                if (sp instanceof Context.BuiltinSwitchPoint && !sp.hasBeenInvalidated()) {
+                    return new GuardedInvocation(GlobalConstants.staticConstantGetter(find.getObjectValue()), guard, sp, null);
+                }
 
-                if (link != null) {
-                    final MethodHandle invocation = link.getInvocation(); //this contains the builtin switchpoint
+                if (find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) {
+                    // If property is found in the prototype object bind the method handle directly to
+                    // the proto filter instead of going through wrapper instantiation below.
+                    final ScriptObject proto = wrappedReceiver.getProto();
+                    final GuardedInvocation link = proto.lookup(desc, request);
 
-                    final MethodHandle adaptedInvocation = MH.asType(invocation, invocation.type().changeParameterType(0, Object.class));
-                    final MethodHandle method = MH.filterArguments(adaptedInvocation, 0, protoFilter);
-                    final MethodHandle protoGuard = MH.filterArguments(link.getGuard(), 0, protoFilter);
-
-                    return new GuardedInvocation(method, NashornGuards.combineGuards(guard, protoGuard));
+                    if (link != null) {
+                        final MethodHandle invocation = link.getInvocation(); //this contains the builtin switchpoint
+                        final MethodHandle adaptedInvocation = MH.asType(invocation, invocation.type().changeParameterType(0, Object.class));
+                        final MethodHandle method = MH.filterArguments(adaptedInvocation, 0, protoFilter);
+                        final MethodHandle protoGuard = MH.filterArguments(link.getGuard(), 0, protoFilter);
+                        return new GuardedInvocation(method, NashornGuards.combineGuards(guard, protoGuard));
+                    }
                 }
             }
+            break;
+        case "setProp":
+        case "setElem":
+            return getPrimitiveSetter(name, guard, wrapFilter, NashornCallSiteDescriptor.isStrict(desc));
+        default:
+            break;
         }
 
         final GuardedInvocation link = wrappedReceiver.lookup(desc, request);
@@ -138,4 +167,41 @@
 
         return null;
     }
+
+    private static GuardedInvocation getPrimitiveSetter(final String name, final MethodHandle guard,
+                                                        final MethodHandle wrapFilter, final boolean isStrict) {
+        MethodHandle filter = MH.asType(wrapFilter, wrapFilter.type().changeReturnType(ScriptObject.class));
+        final MethodHandle target;
+
+        if (name == null) {
+            filter = MH.dropArguments(filter, 1, Object.class, Object.class);
+            target = MH.insertArguments(PRIMITIVE_SETTER, 3, isStrict);
+        } else {
+            filter = MH.dropArguments(filter, 1, Object.class);
+            target = MH.insertArguments(PRIMITIVE_SETTER, 2, name, isStrict);
+        }
+
+        return new GuardedInvocation(MH.foldArguments(target, filter), guard);
+    }
+
+
+    @SuppressWarnings("unused")
+    private static void primitiveSetter(final ScriptObject wrappedSelf, final Object self, final Object key,
+                                        final boolean strict, final Object value) {
+        // See ES5.1 8.7.2 PutValue (V, W)
+        final String name = JSType.toString(key);
+        final FindProperty find = wrappedSelf.findProperty(name, true);
+        if (find == null || !(find.getProperty() instanceof UserAccessorProperty) || !find.getProperty().isWritable()) {
+            if (strict) {
+                throw typeError("property.not.writable", name, ScriptRuntime.safeToString(self));
+            }
+            return;
+        }
+        // property found and is a UserAccessorProperty
+        find.setValue(value, strict);
+    }
+
+    private static MethodHandle findOwnMH(final String name, final MethodType type) {
+        return MH.findStatic(MethodHandles.lookup(), PrimitiveLookup.class, name, type);
+    }
 }
diff --git a/src/jdk/nashorn/internal/runtime/logging/DebugLogger.java b/src/jdk/nashorn/internal/runtime/logging/DebugLogger.java
index 084f765..99936c5 100644
--- a/src/jdk/nashorn/internal/runtime/logging/DebugLogger.java
+++ b/src/jdk/nashorn/internal/runtime/logging/DebugLogger.java
@@ -99,10 +99,10 @@
                         final StringBuilder sb = new StringBuilder();
 
                         sb.append('[')
-                           .append(record.getLoggerName())
-                           .append("] ")
-                           .append(record.getMessage())
-                           .append('\n');
+                        .append(record.getLoggerName())
+                        .append("] ")
+                        .append(record.getMessage())
+                        .append('\n');
 
                         return sb.toString();
                     }
@@ -194,7 +194,7 @@
      */
     public void indent(final int pos) {
         if (isEnabled) {
-           indent += pos * INDENT_SPACE;
+            indent += pos * INDENT_SPACE;
         }
     }
 
@@ -227,57 +227,14 @@
     }
 
     /**
-     * Check if the logger is above the level of detail given
+     * Check if the event of given level will be logged.
      * @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
+     * @return true if event of given level will be logged.
      */
-    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();
+    public boolean isLoggable(final Level level) {
+        return logger.isLoggable(level);
     }
 
     /**
@@ -566,7 +523,7 @@
      * @param str   string to log
      */
     public void log(final Level level, final String str) {
-        if (isEnabled && !isQuiet) {
+        if (isEnabled && !isQuiet && logger.isLoggable(level)) {
             final StringBuilder sb = new StringBuilder();
             for (int i = 0 ; i < indent ; i++) {
                 sb.append(' ');
@@ -584,7 +541,7 @@
      * @param objs  objects for which to invoke toString and concatenate to log
      */
     public void log(final Level level, final Object... objs) {
-        if (isEnabled && !isQuiet) {
+        if (isEnabled && !isQuiet && logger.isLoggable(level)) {
             final StringBuilder sb = new StringBuilder();
             for (final Object obj : objs) {
                 sb.append(obj);
diff --git a/src/jdk/nashorn/internal/runtime/options/OptionTemplate.java b/src/jdk/nashorn/internal/runtime/options/OptionTemplate.java
index b6790aa..2fae703 100644
--- a/src/jdk/nashorn/internal/runtime/options/OptionTemplate.java
+++ b/src/jdk/nashorn/internal/runtime/options/OptionTemplate.java
@@ -163,7 +163,7 @@
 
     /**
      * Does this option automatically enable another option, i.e. a dependency.
-     * @return the dependecy or null if non exists
+     * @return the dependency or null if none exists
      */
     public String getDependency() {
         return this.dependency;
@@ -304,8 +304,8 @@
         }
     }
 
-    boolean matches(final String key0) {
-        return key0.equals(this.shortName) || key0.equals(this.name);
+    boolean nameMatches(final String aName) {
+        return aName.equals(this.shortName) || aName.equals(this.name);
     }
 
     private static final int LINE_BREAK = 64;
diff --git a/src/jdk/nashorn/internal/runtime/options/Options.java b/src/jdk/nashorn/internal/runtime/options/Options.java
index ed39fa9..f85c4f2 100644
--- a/src/jdk/nashorn/internal/runtime/options/Options.java
+++ b/src/jdk/nashorn/internal/runtime/options/Options.java
@@ -42,6 +42,7 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.MissingResourceException;
+import java.util.Objects;
 import java.util.PropertyPermission;
 import java.util.ResourceBundle;
 import java.util.StringTokenizer;
@@ -135,6 +136,12 @@
         return options.toString();
     }
 
+    private static void checkPropertyName(final String name) {
+        if (! Objects.requireNonNull(name).startsWith("nashorn.")) {
+            throw new IllegalArgumentException(name);
+        }
+    }
+
     /**
      * Convenience function for getting system properties in a safe way
 
@@ -143,11 +150,7 @@
      * @return true if set to true, default value if unset or set to false
      */
     public static boolean getBooleanProperty(final String name, final Boolean defValue) {
-        name.getClass(); // null check
-        if (!name.startsWith("nashorn.")) {
-            throw new IllegalArgumentException(name);
-        }
-
+        checkPropertyName(name);
         return AccessController.doPrivileged(
                 new PrivilegedAction<Boolean>() {
                     @Override
@@ -184,11 +187,7 @@
      * @return string property if set or default value
      */
     public static String getStringProperty(final String name, final String defValue) {
-        name.getClass(); // null check
-        if (! name.startsWith("nashorn.")) {
-            throw new IllegalArgumentException(name);
-        }
-
+        checkPropertyName(name);
         return AccessController.doPrivileged(
                 new PrivilegedAction<String>() {
                     @Override
@@ -211,11 +210,7 @@
      * @return integer property if set or default value
      */
     public static int getIntProperty(final String name, final int defValue) {
-        name.getClass(); // null check
-        if (! name.startsWith("nashorn.")) {
-            throw new IllegalArgumentException(name);
-        }
-
+        checkPropertyName(name);
         return AccessController.doPrivileged(
                 new PrivilegedAction<Integer>() {
                     @Override
@@ -423,9 +418,17 @@
     public void process(final String[] args) {
         final LinkedList<String> argList = new LinkedList<>();
         addSystemProperties(NASHORN_ARGS_PREPEND_PROPERTY, argList);
+        processArgList(argList);
+        assert argList.isEmpty();
         Collections.addAll(argList, args);
+        processArgList(argList);
+        assert argList.isEmpty();
         addSystemProperties(NASHORN_ARGS_PROPERTY, argList);
+        processArgList(argList);
+        assert argList.isEmpty();
+    }
 
+    private void processArgList(final LinkedList<String> argList) {
         while (!argList.isEmpty()) {
             final String arg = argList.remove(0);
 
@@ -516,9 +519,25 @@
         }
     }
 
-    private static OptionTemplate getOptionTemplate(final String key) {
+    /**
+     * Retrieves an option template identified by key.
+     * @param shortKey the short (that is without the e.g. "nashorn.option." part) key
+     * @return the option template identified by the key
+     * @throws IllegalArgumentException if the key doesn't specify an existing template
+     */
+    public OptionTemplate getOptionTemplateByKey(final String shortKey) {
+        final String fullKey = key(shortKey);
+        for(final OptionTemplate t: validOptions) {
+            if(t.getKey().equals(fullKey)) {
+                return t;
+            }
+        }
+        throw new IllegalArgumentException(shortKey);
+    }
+
+    private static OptionTemplate getOptionTemplateByName(final String name) {
         for (final OptionTemplate t : Options.validOptions) {
-            if (t.matches(key)) {
+            if (t.nameMatches(name)) {
                 return t;
             }
         }
@@ -678,7 +697,7 @@
             }
 
             final String token = st.nextToken();
-            this.template = Options.getOptionTemplate(token);
+            this.template = getOptionTemplateByName(token);
             if (this.template == null) {
                 throw new IllegalArgumentException(argument);
             }
diff --git a/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java b/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java
index 77b1b3d..2d37a76 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/RegExpFactory.java
@@ -26,7 +26,7 @@
 package jdk.nashorn.internal.runtime.regexp;
 
 import java.util.Collections;
-import java.util.Set;
+import java.util.Map;
 import java.util.WeakHashMap;
 import jdk.nashorn.internal.runtime.ParserException;
 import jdk.nashorn.internal.runtime.options.Options;
@@ -45,11 +45,10 @@
     /** Weak cache of already validated regexps - when reparsing, we don't, for example
      *  need to recompile (reverify) all regexps that have previously been parsed by this
      *  RegExpFactory in a previous compilation. This saves significant time in e.g. avatar
-     *  startup */
-    private static final Set<String> VALID_CACHE_SET =
-            Collections.newSetFromMap(
-                    Collections.synchronizedMap(
-                            new WeakHashMap<String, Boolean>()));
+     *  startup
+     */
+    private static final Map<String, RegExp> REGEXP_CACHE =
+            Collections.synchronizedMap(new WeakHashMap<String, RegExp>());
 
     static {
         final String impl = Options.getStringProperty("nashorn.regexp.impl", JONI);
@@ -87,7 +86,13 @@
      * @throws ParserException if invalid source or flags
      */
     public static RegExp create(final String pattern, final String flags) {
-        return instance.compile(pattern,  flags);
+        final String key = pattern + "/" + flags;
+        RegExp regexp = REGEXP_CACHE.get(key);
+        if (regexp == null) {
+            regexp = instance.compile(pattern,  flags);
+            REGEXP_CACHE.put(key, regexp);
+        }
+        return regexp;
     }
 
     /**
@@ -98,11 +103,8 @@
      *
      * @throws ParserException if invalid source or flags
      */
-    // @SuppressWarnings({"unused"})
     public static void validate(final String pattern, final String flags) throws ParserException {
-        if (VALID_CACHE_SET.add(pattern + flags)) {
-            instance.compile(pattern, flags);
-        }
+        create(pattern, flags);
     }
 
     /**
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java b/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java
index 0e78933..b343d77 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java
@@ -145,9 +145,6 @@
             case TargetInfo.IS_EMPTY_MEM:
                 addOpcode(OPCode.NULL_CHECK_END_MEMST);
                 break;
-            case TargetInfo.IS_EMPTY_REC:
-                addOpcode(OPCode.NULL_CHECK_END_MEMST_PUSH);
-                break;
             default:
                 break;
             } // switch
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java b/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java
index 30cfe90..dbed5d1 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java
@@ -183,7 +183,6 @@
                 case OPCode.NULL_CHECK_START:           opNullCheckStart();        continue;
                 case OPCode.NULL_CHECK_END:             opNullCheckEnd();          continue;
                 case OPCode.NULL_CHECK_END_MEMST:       opNullCheckEndMemST();     continue;
-                case OPCode.NULL_CHECK_END_MEMST_PUSH:  opNullCheckEndMemSTPush(); continue;
 
                 case OPCode.JUMP:                       opJump();                  continue;
                 case OPCode.PUSH:                       opPush();                  continue;
@@ -1025,29 +1024,6 @@
         }
     }
 
-    // USE_SUBEXP_CALL
-    private void opNullCheckEndMemSTPush() {
-        final int mem = code[ip++];   /* mem: null check id */
-
-        int isNull;
-        if (Config.USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT) {
-            isNull = nullCheckMemStRec(mem, s);
-        } else {
-            isNull = nullCheckRec(mem, s);
-        }
-
-        if (isNull != 0) {
-            if (Config.DEBUG_MATCH) {
-                Config.log.println("NULL_CHECK_END_MEMST_PUSH: skip  id:" + mem + ", s:" + s);
-            }
-
-            if (isNull == -1) {opFail(); return;}
-            nullCheckFound();
-        } else {
-            pushNullCheckEnd(mem);
-        }
-    }
-
     private void opJump() {
         ip += code[ip] + 1;
     }
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/Config.java b/src/jdk/nashorn/internal/runtime/regexp/joni/Config.java
index e55947c..6590053 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/Config.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Config.java
@@ -65,7 +65,7 @@
 
     final boolean DONT_OPTIMIZE                     = false;
 
-    final boolean USE_STRING_TEMPLATES              = true; // use embeded string templates in Regex object as byte arrays instead of compiling them into int bytecode array
+    final boolean USE_STRING_TEMPLATES              = true; // use embedded string templates in Regex object as byte arrays instead of compiling them into int bytecode array
 
     final boolean NON_UNICODE_SDW                   = true;
 
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java b/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java
index af2d9a6..a0a4353 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java
@@ -229,6 +229,11 @@
 
     /**
      * @see <a href="http://www.geocities.jp/kosako3/oniguruma/doc/RE.txt">http://www.geocities.jp/kosako3/oniguruma/doc/RE.txt</a>
+     *
+     * @param code code
+     * @param ctype ctype
+     *
+     * @return isCodeCType
      */
     public static boolean isCodeCType(final int code, final int ctype) {
         int type;
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java b/src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java
index fc498c4..4cc33ba 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java
@@ -19,7 +19,6 @@
  */
 package jdk.nashorn.internal.runtime.regexp.joni;
 
-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;
@@ -369,118 +368,9 @@
         }
     }
 
-    protected final int nullCheckRec(final int id, final int s) {
-        int level = 0;
-        int k = stk;
-        while (true) {
-            k--;
-            final StackEntry e = stack[k];
-
-            if (e.type == NULL_CHECK_START) {
-                if (e.getNullCheckNum() == id) {
-                    if (level == 0) {
-                        return e.getNullCheckPStr() == s ? 1 : 0;
-                    }
-                    level--;
-                }
-            } else if (e.type == NULL_CHECK_END) {
-                level++;
-            }
-        }
-    }
-
     protected final int nullCheckMemSt(final int id, final int s) {
-        int k = stk;
-        int isNull;
-        while (true) {
-            k--;
-            StackEntry e = stack[k];
-
-            if (e.type == NULL_CHECK_START) {
-                if (e.getNullCheckNum() == id) {
-                    if (e.getNullCheckPStr() != s) {
-                        isNull = 0;
-                        break;
-                    }
-                    int endp;
-                    isNull = 1;
-                    while (k < stk) {
-                        if (e.type == MEM_START) {
-                            if (e.getMemEnd() == INVALID_INDEX) {
-                                isNull = 0;
-                                break;
-                            }
-                            if (bsAt(regex.btMemEnd, e.getMemNum())) {
-                                endp = stack[e.getMemEnd()].getMemPStr();
-                            } else {
-                                endp = e.getMemEnd();
-                            }
-                            if (stack[e.getMemStart()].getMemPStr() != endp) {
-                                isNull = 0;
-                                break;
-                            } else if (endp != s) {
-                                isNull = -1; /* empty, but position changed */
-                            }
-                        }
-                        k++;
-                        e = stack[k]; // !!
-                    }
-                    break;
-                }
-            }
-        }
-        return isNull;
-    }
-
-    protected final int nullCheckMemStRec(final int id, final int s) {
-        int level = 0;
-        int k = stk;
-        int isNull;
-        while (true) {
-            k--;
-            StackEntry e = stack[k];
-
-            if (e.type == NULL_CHECK_START) {
-                if (e.getNullCheckNum() == id) {
-                    if (level == 0) {
-                        if (e.getNullCheckPStr() != s) {
-                            isNull = 0;
-                            break;
-                        }
-                        int endp;
-                        isNull = 1;
-                        while (k < stk) {
-                            if (e.type == MEM_START) {
-                                if (e.getMemEnd() == INVALID_INDEX) {
-                                    isNull = 0;
-                                    break;
-                                }
-                                if (bsAt(regex.btMemEnd, e.getMemNum())) {
-                                    endp = stack[e.getMemEnd()].getMemPStr();
-                                } else {
-                                    endp = e.getMemEnd();
-                                }
-                                if (stack[e.getMemStart()].getMemPStr() != endp) {
-                                    isNull = 0;
-                                    break;
-                                } else if (endp != s) {
-                                    isNull = -1; /* empty, but position changed */
-                                }
-                            }
-                            k++;
-                            e = stack[k];
-                        }
-                        break;
-                    }
-                    level--;
-                }
-            } else if (e.type == NULL_CHECK_END) {
-                if (e.getNullCheckNum() == id) {
-                    level++;
-                }
-            }
-        }
-        return isNull;
+        // Return -1 here to cause operation to fail
+        return -nullCheck(id, s);
     }
 
     protected final int getRepeat(final int id) {
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java b/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java
index f58b85f..97f57e9 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java
@@ -57,10 +57,10 @@
         }
     }
 
-    /**
-     * OP
-     *
-     */
+    //
+    // OP
+    //
+
     protected boolean isOp(final int opm) {
         return (op & opm) != 0;
     }
@@ -189,11 +189,10 @@
         return isOp(OP_ESC_X_BRACE_HEX8);
     }
 
+    //
+    // OP2
+    //
 
-    /**
-     * OP
-     *
-     */
     protected boolean isOp2(final int opm) {
         return (op2 & opm) != 0;
     }
@@ -278,10 +277,10 @@
         return isOp2(OP2_INEFFECTIVE_ESCAPE);
     }
 
-    /**
-     * BEHAVIOR
-     *
-     */
+    //
+    // BEHAVIOR
+    //
+
     protected boolean isBehavior(final int bvm) {
         return (behavior & bvm) != 0;
     }
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/TargetInfo.java b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/TargetInfo.java
index 8dfb92b..5708a39 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/constants/TargetInfo.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/constants/TargetInfo.java
@@ -24,5 +24,4 @@
     final int ISNOT_EMPTY   = 0;
     final int IS_EMPTY      = 1;
     final int IS_EMPTY_MEM  = 2;
-    final int IS_EMPTY_REC  = 3;
 }
diff --git a/src/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java b/src/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java
index 537bf0f..a3892c7 100644
--- a/src/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java
+++ b/src/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java
@@ -24,6 +24,6 @@
     private static final long serialVersionUID = -6027192180014164667L;
 
     public JOniException(final String message) {
-        super(message);
+        super(message, null, false, false);
     }
 }
diff --git a/src/jdk/nashorn/internal/runtime/resources/Messages.properties b/src/jdk/nashorn/internal/runtime/resources/Messages.properties
index 119277d..003887c 100644
--- a/src/jdk/nashorn/internal/runtime/resources/Messages.properties
+++ b/src/jdk/nashorn/internal/runtime/resources/Messages.properties
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@
 lexer.error.json.invalid.number=Invalid JSON number format
 lexer.error.invalid.escape.char=Invalid escape character
 lexer.error.illegal.identifier.character=Illegal character in identifier
+lexer.error.here.non.matching.delimiter=Quoted here string end marker must have matching delimiters
 
 parser.error.illegal.continue.stmt=Illegal continue statement
 parser.error.illegal.break.stmt=Illegal break statement
@@ -78,6 +79,7 @@
 type.error.not.a.regexp={0} is not a RegExp
 type.error.not.a.string={0} is not a String
 type.error.not.a.function={0} is not a function
+type.error.not.a.function.value={0}, which has value {1}, 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
@@ -121,7 +123,7 @@
 type.error.cannot.get.default.number=Cannot get default number value
 type.error.cant.apply.with.to.null=Cannot apply "with" to null
 type.error.cant.apply.with.to.undefined=Cannot apply "with" to undefined
-type.error.cant.apply.with.to.non.scriptobject=Cannot apply "with" to non script object
+type.error.cant.apply.with.to.non.scriptobject=Cannot apply "with" to non script object. Consider using "with(Object.bindProperties('{'}, nonScriptObject))".
 type.error.in.with.non.object=Right hand side of "in" cannot be non-Object, found {0}
 type.error.prototype.not.an.object="prototype" of {0} is not an Object, it is {1}
 type.error.cant.load.script=Cannot load script from {0}
@@ -141,11 +143,14 @@
 type.error.extend.ERROR_MULTIPLE_SUPERCLASSES=Can not extend multiple classes {0}. At most one of the specified types can be a class, the rest must all be interfaces.
 type.error.extend.ERROR_NO_COMMON_LOADER=Can not find a common class loader for ScriptObject and {0}.
 type.error.extend.ERROR_FINAL_FINALIZER=Can not extend class because {0} has a final finalize method.
+type.error.extend.ERROR_OTHER=Can not extend/implement {0} because of {1}
 type.error.no.constructor.matches.args=Can not construct {0} with the passed arguments; they do not match any of its constructor signatures.
 type.error.no.method.matches.args=Can not invoke method {0} with the passed arguments; they do not match any of its method signatures.
+type.error.no.constructor.matches.args=Can not create new object with constructor {0} with the passed arguments; they do not match any of its method signatures.
 type.error.method.not.constructor=Java method {0} cannot 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.java.array.conversion.failed=Java.to conversion to array type {0} failed
 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}.
 
@@ -159,6 +164,7 @@
 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
+range.error.exec.returned.non.zero=$EXEC returned non-zero exit code: {0}
 
 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
@@ -166,11 +172,12 @@
 syntax.error.invalid.json=Invalid JSON: {0}
 syntax.error.strict.cant.delete=cannot delete "{0}" in strict mode
 syntax.error.redeclare.variable=Variable "{0}" has already been declared
-syntax.error.assign.constant=Assignment to constant "{0}"
 syntax.error.unprotected.switch.declaration=Unsupported {0} declaration in unprotected switch statement
 
 io.error.cant.write=cannot write "{0}"
+
 config.error.no.dest=no destination directory supplied
+config.error.eagerCompilationConflictsWithOptimisticTypes={0}=false (eager compilation) is not compatible with {1}=true.
 
 uri.error.bad.uri=Bad URI "{0}" near offset {1}
-
+list.adapter.null.global=Attempted to create the adapter from outside a JavaScript execution context.
diff --git a/src/jdk/nashorn/internal/runtime/resources/Options.properties b/src/jdk/nashorn/internal/runtime/resources/Options.properties
index 57943e0..98adecb 100644
--- a/src/jdk/nashorn/internal/runtime/resources/Options.properties
+++ b/src/jdk/nashorn/internal/runtime/resources/Options.properties
@@ -114,7 +114,7 @@
     short_name="-d",                                             \
     is_undocumented=true,                                        \
     params="<path>",                                             \
-    desc="specify a destination directory to dump class files.", \
+    desc="specify a destination directory to dump source and class files.", \
     type=String                                                  \
 }
 
diff --git a/src/jdk/nashorn/internal/runtime/resources/parser.js b/src/jdk/nashorn/internal/runtime/resources/parser.js
index 8671d36..94d02ab 100644
--- a/src/jdk/nashorn/internal/runtime/resources/parser.js
+++ b/src/jdk/nashorn/internal/runtime/resources/parser.js
@@ -55,7 +55,7 @@
                 // do not start with '/'. If regexp, then eval it to make RegExp object
                 return value.startsWith('/')? eval(value) : value.substring(1);
             } else {
-                // anythin else is returned "as is""
+                // anything else is returned "as is"
                 return value;
             }
         });
diff --git a/src/jdk/nashorn/internal/scripts/JD.java b/src/jdk/nashorn/internal/scripts/JD.java
new file mode 100644
index 0000000..11d6cac
--- /dev/null
+++ b/src/jdk/nashorn/internal/scripts/JD.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.scripts;
+
+import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.ScriptObject;
+
+/**
+ * Empty object class for dual primitive-object fields.
+ */
+public class JD extends ScriptObject {
+
+    private static final PropertyMap map$ = PropertyMap.newMap(JD.class);
+
+    /**
+     * Returns the initial property map to be used.
+     * @return the initial property map.
+     */
+    public static PropertyMap getInitialMap() {
+        return map$;
+    }
+
+    /**
+     * Constructor given an initial property map
+     *
+     * @param map the property map
+     */
+    public JD(final PropertyMap map) {
+        super(map);
+    }
+
+    /**
+     * Constructor given an initial prototype and the default initial property map.
+     *
+     * @param proto the prototype object
+     */
+    public JD(final ScriptObject proto) {
+        super(proto, getInitialMap());
+    }
+
+    /**
+     * Constructor that takes a pre-initialized spill pool. Used by
+     * {@link jdk.nashorn.internal.codegen.SpillObjectCreator} and
+     * {@link jdk.nashorn.internal.parser.JSONParser} for initializing object literals
+     *
+     * @param map            property map
+     * @param primitiveSpill primitive spill pool
+     * @param objectSpill    reference spill pool
+     */
+    public JD(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
+     *
+     * @return newly allocated ScriptObject
+     */
+    public static ScriptObject allocate(final PropertyMap map) {
+        return new JD(map);
+    }
+}
+
diff --git a/src/jdk/nashorn/internal/scripts/JO.java b/src/jdk/nashorn/internal/scripts/JO.java
index e5346cb..1f9aa7c 100644
--- a/src/jdk/nashorn/internal/scripts/JO.java
+++ b/src/jdk/nashorn/internal/scripts/JO.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,16 +25,15 @@
 
 package jdk.nashorn.internal.scripts;
 
-import jdk.nashorn.internal.codegen.SpillObjectCreator;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptObject;
 
 /**
- * Empty object class.
+ * Empty object class for object-only fields.
  */
 public class JO extends ScriptObject {
 
-    private static final PropertyMap map$ = PropertyMap.newMap();
+    private static final PropertyMap map$ = PropertyMap.newMap(JO.class);
 
     /**
      * Returns the initial property map to be used.
@@ -54,18 +53,18 @@
     }
 
     /**
-     * Constructor given an initial prototype and an initial property map.
+     * Constructor given an initial prototype and the default initial property map.
      *
      * @param proto the prototype object
-     * @param map the property map
      */
-    public JO(final ScriptObject proto, final PropertyMap map) {
-        super(proto, map);
+    public JO(final ScriptObject proto) {
+        super(proto, getInitialMap());
     }
 
     /**
-     * Constructor that takes a pre-initialized spill pool. Used for
-     * by {@link SpillObjectCreator} for intializing object literals
+     * Constructor that takes a pre-initialized spill pool. Used by
+     * {@link jdk.nashorn.internal.codegen.SpillObjectCreator} and
+     * {@link jdk.nashorn.internal.parser.JSONParser} for initializing object literals
      *
      * @param map            property map
      * @param primitiveSpill primitive spill pool
@@ -86,3 +85,4 @@
         return new JO(map);
     }
 }
+
diff --git a/src/jdk/nashorn/tools/Shell.java b/src/jdk/nashorn/tools/Shell.java
index 58ab97c..9ee02af 100644
--- a/src/jdk/nashorn/tools/Shell.java
+++ b/src/jdk/nashorn/tools/Shell.java
@@ -54,7 +54,6 @@
 import jdk.nashorn.internal.runtime.ScriptEnvironment;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
-import jdk.nashorn.internal.runtime.Source;
 import jdk.nashorn.internal.runtime.options.Options;
 
 /**
@@ -109,7 +108,10 @@
      */
     public static void main(final String[] args) {
         try {
-            System.exit(main(System.in, System.out, System.err, args));
+            final int exitCode = main(System.in, System.out, System.err, args);
+            if (exitCode != SUCCESS) {
+                System.exit(exitCode);
+            }
         } catch (final IOException e) {
             System.err.println(e); //bootstrapping, Context.err may not exist
             System.exit(IO_ERROR);
@@ -252,12 +254,9 @@
                     return COMPILATION_ERROR;
                 }
 
-                new Compiler(
+                Compiler.forNoInstallerCompilation(
                        context,
-                       env,
-                       null, //null - pass no code installer - this is compile only
                        functionNode.getSource(),
-                       context.getErrorManager(),
                        env._strict | functionNode.isStrict()).
                        compile(functionNode, CompilationPhases.COMPILE_ALL_NO_INSTALL);
 
@@ -414,18 +413,7 @@
                 Context.setGlobal(global);
             }
 
-            // initialize with "shell.js" script
-            try {
-                final Source source = sourceFor("<shell.js>", Shell.class.getResource("resources/shell.js"));
-                context.eval(global, source.getString(), global, "<shell.js>", false);
-            } catch (final Exception e) {
-                err.println(e);
-                if (env._dump_on_error) {
-                    e.printStackTrace(err);
-                }
-
-                return INTERNAL_ERROR;
-            }
+            global.addShellBuiltins();
 
             while (true) {
                 err.print(prompt);
@@ -447,7 +435,7 @@
                 }
 
                 try {
-                    final Object res = context.eval(global, source, global, "<shell>", env._strict);
+                    final Object res = context.eval(global, source, global, "<shell>");
                     if (res != ScriptRuntime.UNDEFINED) {
                         err.println(JSType.toString(res));
                     }
diff --git a/src/jdk/nashorn/tools/ShellFunctions.java b/src/jdk/nashorn/tools/ShellFunctions.java
new file mode 100644
index 0000000..0c4e4cb
--- /dev/null
+++ b/src/jdk/nashorn/tools/ShellFunctions.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.tools;
+
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import jdk.nashorn.internal.runtime.JSType;
+import jdk.nashorn.internal.objects.Global;
+
+/**
+ * Global functions supported only in shell interactive mode.
+ */
+public final class ShellFunctions {
+
+    /** Handle to implementation of {@link ShellFunctions#input} - Nashorn extension */
+    public static final MethodHandle INPUT = findOwnMH("input", Object.class, Object.class, Object.class, Object.class);
+
+    /** Handle to implementation of {@link ShellFunctions#evalinput} - Nashorn extension */
+    public static final MethodHandle EVALINPUT = findOwnMH("evalinput",     Object.class, Object.class, Object.class, Object.class);
+
+    private ShellFunctions() {
+    }
+
+    /**
+     * Nashorn extension: global.input (shell-interactive-mode-only)
+     * Read one or more lines of input from the standard input till the
+     * given end marker is seen in standard input.
+     *
+     * @param self   self reference
+     * @param endMarker String used as end marker for input
+     * @param prompt String used as input prompt
+     *
+     * @return line that was read
+     *
+     * @throws IOException if an exception occurs
+     */
+    public static Object input(final Object self, final Object endMarker, final Object prompt) throws IOException {
+        final String endMarkerStr = (endMarker != UNDEFINED)? JSType.toString(endMarker) : "";
+        final String promptStr = (prompt != UNDEFINED)? JSType.toString(prompt)  : ">> ";
+        final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
+        final StringBuilder buf = new StringBuilder();
+        while (true) {
+            System.out.print(promptStr);
+            final String line = reader.readLine();
+            if (line == null || line.equals(endMarkerStr)) {
+                break;
+            }
+            buf.append(line);
+            buf.append('\n');
+        }
+        return buf.toString();
+    }
+
+    /**
+     * Nashorn extension: Reads zero or more lines from standard input and
+     * evaluates the concatenated string as code
+     *
+     * @param self self reference
+     * @param endMarker String used as end marker for input
+     * @param prompt String used as input prompt
+     *
+     * @return output from evaluating the script
+     *
+     * @throws IOException if an exception occurs
+     */
+    public static Object evalinput(final Object self, final Object endMarker, final Object prompt) throws IOException {
+        return Global.eval(self, input(self, endMarker, prompt));
+    }
+
+    private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
+        return MH.findStatic(MethodHandles.lookup(), ShellFunctions.class, name, MH.type(rtype, types));
+    }
+}
diff --git a/src/jdk/nashorn/tools/resources/shell.js b/src/jdk/nashorn/tools/resources/shell.js
deleted file mode 100644
index fdfde7a..0000000
--- a/src/jdk/nashorn/tools/resources/shell.js
+++ /dev/null
@@ -1,83 +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.
- */
-
-/*
- * Initialization script for shell when running in interactive mode.
- */
-
-/**
- * Reads zero or more lines from standard input and returns concatenated string
- *
- * @param endMarker marker string that signals end of input
- * @param prompt prompt printed for each line
- */
-Object.defineProperty(this, "input", {
-    value: function input(endMarker, prompt) {
-        if (!endMarker) {
-            endMarker = "";
-        }
-
-        if (!prompt) {
-            prompt = " >> ";
-        }
-
-        var imports = new JavaImporter(java.io, java.lang);
-        var str = "";
-        with (imports) {
-            var reader = new BufferedReader(new InputStreamReader(System['in']));
-            var line;
-            while (true) {
-                System.out.print(prompt);
-                line = reader.readLine();
-                if (line == null || line == endMarker) {
-                    break;
-                }
-                str += line + "\n";
-            }
-        }
-
-        return str;
-    },
-    enumerable: false,
-    writable: true,
-    configurable: true
-});
-
-
-/**
- * Reads zero or more lines from standard input and evaluates the concatenated
- * string as code
- *
- * @param endMarker marker string that signals end of input
- * @param prompt prompt printed for each line
- */
-Object.defineProperty(this, "evalinput", {
-    value: function evalinput(endMarker, prompt) {
-        var code = input(endMarker, prompt);
-        // make sure everything is evaluated in global scope!
-        return this.eval(code);
-    },
-    enumerable: false,
-    writable: true,
-    configurable: true
-});
diff --git a/test/examples/json-parser-micro.js b/test/examples/json-parser-micro.js
new file mode 100644
index 0000000..619c35f
--- /dev/null
+++ b/test/examples/json-parser-micro.js
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+function bench() {
+    var start = Date.now();
+    for (var i = 0; i < 2000; i++) {
+        JSON.parse(String(json));
+    }
+    print("1000 iterations in", Date.now() - start, "millis");
+}
+
+var json = '[\
+  {\
+    "_id": "54ca34171d3ade49782294c8",\
+    "index": 0,\
+    "guid": "ed0e74d5-ac63-47b6-8938-1750abab5770",\
+    "isActive": false,\
+    "balance": "$1,996.19",\
+    "picture": "http://placehold.it/32x32",\
+    "age": 39,\
+    "eyeColor": "green",\
+    "name": "Rose Graham",\
+    "gender": "male",\
+    "company": "PRIMORDIA",\
+    "email": "rosegraham@primordia.com",\
+    "phone": "+1 (985) 600-3551",\
+    "address": "364 Melba Court, Succasunna, Texas, 8393",\
+    "about": "Sunt commodo cillum occaecat velit eu eiusmod ex eiusmod sunt deserunt nulla proident incididunt. Incididunt ullamco Lorem elit do culpa esse do ex dolor aliquip labore. Ullamco velit laboris incididunt dolor. Nostrud dolor sint pariatur fugiat ullamco exercitation. Eu laboris do cupidatat eiusmod incididunt mollit occaecat voluptate.",\
+    "registered": "2014-03-13T12:05:14 -01:00",\
+    "latitude": 18.55665,\
+    "longitude": 81.641001,\
+    "tags": [\
+      "sint",\
+      "Lorem",\
+      "veniam",\
+      "quis",\
+      "proident",\
+      "consectetur",\
+      "consequat"\
+    ],\
+    "friends": [\
+      {\
+        "id": 0,\
+        "name": "Evangelina Morgan"\
+      },\
+      {\
+        "id": 1,\
+        "name": "Saunders Snyder"\
+      },\
+      {\
+        "id": 2,\
+        "name": "Walker Wood"\
+      }\
+    ],\
+    "greeting": "Hello, Rose Graham! You have 1 unread messages.",\
+    "favoriteFruit": "strawberry"\
+  },\
+  {\
+    "_id": "54ca34176790c4c60fcae085",\
+    "index": 1,\
+    "guid": "9dc42e4c-b58f-4d92-a2ee-968d2b627d92",\
+    "isActive": true,\
+    "balance": "$3,832.97",\
+    "picture": "http://placehold.it/32x32",\
+    "age": 40,\
+    "eyeColor": "brown",\
+    "name": "Delaney Cherry",\
+    "gender": "male",\
+    "company": "INJOY",\
+    "email": "delaneycherry@injoy.com",\
+    "phone": "+1 (807) 463-2295",\
+    "address": "470 Hale Avenue, Mulberry, District Of Columbia, 5455",\
+    "about": "Deserunt sit cupidatat elit Lorem excepteur ex. Magna officia minim cupidatat nulla enim deserunt. Amet ex in tempor commodo consequat non ad qui elit cupidatat esse labore sint.",\
+    "registered": "2014-03-27T23:06:33 -01:00",\
+    "latitude": -4.984238,\
+    "longitude": 116.039285,\
+    "tags": [\
+      "minim",\
+      "velit",\
+      "aute",\
+      "minim",\
+      "id",\
+      "enim",\
+      "enim"\
+    ],\
+    "friends": [\
+      {\
+        "id": 0,\
+        "name": "Barrera Flowers"\
+      },\
+      {\
+        "id": 1,\
+        "name": "Leann Larson"\
+      },\
+      {\
+        "id": 2,\
+        "name": "Latoya Petty"\
+      }\
+    ],\
+    "greeting": "Hello, Delaney Cherry! You have 2 unread messages.",\
+    "favoriteFruit": "strawberry"\
+  },\
+  {\
+    "_id": "54ca3417920666f00c54bfc4",\
+    "index": 2,\
+    "guid": "f91e08f8-1598-49bc-a08b-bb48f0cc1751",\
+    "isActive": true,\
+    "balance": "$2,932.84",\
+    "picture": "http://placehold.it/32x32",\
+    "age": 28,\
+    "eyeColor": "brown",\
+    "name": "Mosley Hammond",\
+    "gender": "male",\
+    "company": "AQUACINE",\
+    "email": "mosleyhammond@aquacine.com",\
+    "phone": "+1 (836) 598-2591",\
+    "address": "879 Columbia Place, Seymour, Montana, 4897",\
+    "about": "Sunt laborum incididunt et elit in deserunt deserunt irure enim ea qui non. Minim nisi sint aute veniam reprehenderit veniam reprehenderit. Elit enim eu voluptate eu cupidatat nulla ea incididunt exercitation voluptate ut aliquip excepteur ipsum. Consequat anim fugiat irure Lorem anim consectetur est.",\
+    "registered": "2014-07-27T05:05:58 -02:00",\
+    "latitude": -43.608015,\
+    "longitude": -38.33894,\
+    "tags": [\
+      "proident",\
+      "incididunt",\
+      "eiusmod",\
+      "anim",\
+      "consectetur",\
+      "qui",\
+      "excepteur"\
+    ],\
+    "friends": [\
+      {\
+        "id": 0,\
+        "name": "Hanson Davidson"\
+      },\
+      {\
+        "id": 1,\
+        "name": "Autumn Kaufman"\
+      },\
+      {\
+        "id": 2,\
+        "name": "Tammy Foley"\
+      }\
+    ],\
+    "greeting": "Hello, Mosley Hammond! You have 4 unread messages.",\
+    "favoriteFruit": "apple"\
+  },\
+  {\
+    "_id": "54ca341753b67572a2b04935",\
+    "index": 3,\
+    "guid": "3377416b-43a2-4f9e-ada3-2479e13b44b8",\
+    "isActive": false,\
+    "balance": "$3,821.54",\
+    "picture": "http://placehold.it/32x32",\
+    "age": 31,\
+    "eyeColor": "green",\
+    "name": "Mueller Barrett",\
+    "gender": "male",\
+    "company": "GROK",\
+    "email": "muellerbarrett@grok.com",\
+    "phone": "+1 (890) 535-2834",\
+    "address": "571 Norwood Avenue, Westwood, Arkansas, 2164",\
+    "about": "Occaecat est sunt commodo ut ex excepteur elit nulla velit minim commodo commodo esse. Lorem quis eu minim consectetur. Cupidatat cupidatat consequat sit eu ex non quis nulla veniam sint enim excepteur. Consequat minim duis do do minim fugiat minim elit laborum ut velit. Occaecat laboris veniam sint reprehenderit.",\
+    "registered": "2014-07-18T17:15:35 -02:00",\
+    "latitude": 10.746577,\
+    "longitude": -160.266041,\
+    "tags": [\
+      "reprehenderit",\
+      "veniam",\
+      "sint",\
+      "commodo",\
+      "exercitation",\
+      "cillum",\
+      "sunt"\
+    ],\
+    "friends": [\
+      {\
+        "id": 0,\
+        "name": "Summers Finch"\
+      },\
+      {\
+        "id": 1,\
+        "name": "Tracie Mcdaniel"\
+      },\
+      {\
+        "id": 2,\
+        "name": "Ayers Patrick"\
+      }\
+    ],\
+    "greeting": "Hello, Mueller Barrett! You have 7 unread messages.",\
+    "favoriteFruit": "apple"\
+  },\
+  {\
+    "_id": "54ca34172775ab9615db0d1d",\
+    "index": 4,\
+    "guid": "a3102a3e-3f08-4df3-b5b5-62eff985d5ca",\
+    "isActive": true,\
+    "balance": "$3,962.27",\
+    "picture": "http://placehold.it/32x32",\
+    "age": 34,\
+    "eyeColor": "green",\
+    "name": "Patrick Foster",\
+    "gender": "male",\
+    "company": "QUAREX",\
+    "email": "patrickfoster@quarex.com",\
+    "phone": "+1 (805) 577-2362",\
+    "address": "640 Richards Street, Roberts, American Samoa, 5530",\
+    "about": "Aute occaecat occaecat ad eiusmod esse aliqua ullamco minim. Exercitation aute ut ex nostrud deserunt laboris officia amet enim do. Cillum officia laborum occaecat eiusmod reprehenderit ex et aliqua minim elit ex aliqua mollit. Occaecat dolor in fugiat laboris aliquip nisi ad voluptate duis eiusmod ad do.",\
+    "registered": "2014-07-22T16:45:35 -02:00",\
+    "latitude": 6.609025,\
+    "longitude": -5.357026,\
+    "tags": [\
+      "ea",\
+      "ut",\
+      "excepteur",\
+      "enim",\
+      "ad",\
+      "non",\
+      "sit"\
+    ],\
+    "friends": [\
+      {\
+        "id": 0,\
+        "name": "Duncan Lewis"\
+      },\
+      {\
+        "id": 1,\
+        "name": "Alyce Benton"\
+      },\
+      {\
+        "id": 2,\
+        "name": "Angelique Larsen"\
+      }\
+    ],\
+    "greeting": "Hello, Patrick Foster! You have 1 unread messages.",\
+    "favoriteFruit": "strawberry"\
+  },\
+  {\
+    "_id": "54ca3417a190f26fef815f6d",\
+    "index": 5,\
+    "guid": "c09663dd-bb0e-45a4-960c-232c0e8a9486",\
+    "isActive": false,\
+    "balance": "$1,871.12",\
+    "picture": "http://placehold.it/32x32",\
+    "age": 20,\
+    "eyeColor": "blue",\
+    "name": "Foreman Chaney",\
+    "gender": "male",\
+    "company": "DEMINIMUM",\
+    "email": "foremanchaney@deminimum.com",\
+    "phone": "+1 (966) 523-2182",\
+    "address": "960 Granite Street, Sunnyside, Tennessee, 1097",\
+    "about": "Adipisicing nisi qui id sit incididunt aute exercitation veniam consequat ipsum sit irure. Aute officia commodo Lorem consequat. Labore exercitation consequat voluptate deserunt consequat do est fugiat nisi eu dolor minim id ea.",\
+    "registered": "2015-01-21T00:18:00 -01:00",\
+    "latitude": -69.841726,\
+    "longitude": 121.809383,\
+    "tags": [\
+      "laboris",\
+      "sunt",\
+      "exercitation",\
+      "enim",\
+      "anim",\
+      "excepteur",\
+      "tempor"\
+    ],\
+    "friends": [\
+      {\
+        "id": 0,\
+        "name": "Espinoza Johnston"\
+      },\
+      {\
+        "id": 1,\
+        "name": "Doreen Holder"\
+      },\
+      {\
+        "id": 2,\
+        "name": "William Ellison"\
+      }\
+    ],\
+    "greeting": "Hello, Foreman Chaney! You have 5 unread messages.",\
+    "favoriteFruit": "strawberry"\
+  }\
+]';
+
+for (var i = 0; i < 100; i++) {
+    bench();
+}
diff --git a/test/script/basic/8024180/with_java_object.js.EXPECTED b/test/script/basic/8024180/with_java_object.js.EXPECTED
index 3f0facf..c3922b0 100644
--- a/test/script/basic/8024180/with_java_object.js.EXPECTED
+++ b/test/script/basic/8024180/with_java_object.js.EXPECTED
@@ -1 +1 @@
-TypeError: Cannot apply "with" to non script object
+TypeError: Cannot apply "with" to non script object. Consider using "with(Object.bindProperties({}, nonScriptObject))".
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8007456.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8007456.js
index dfcad5a..5bcc00b 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8007456.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,15 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * JDK-8007456: Nashorn test framework argument does not handle quoted strings
+ *
+ * @test
+ * @argument "hello world"
+ * @argument "This has spaces"
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+print(arguments.length);
+print(arguments[0]);
+print(arguments[1]);
diff --git a/test/script/basic/JDK-8007456.js.EXPECTED b/test/script/basic/JDK-8007456.js.EXPECTED
new file mode 100644
index 0000000..bc56f76
--- /dev/null
+++ b/test/script/basic/JDK-8007456.js.EXPECTED
@@ -0,0 +1,3 @@
+2
+hello world
+This has spaces
diff --git a/test/script/basic/JDK-8023026.js.EXPECTED b/test/script/basic/JDK-8023026.js.EXPECTED
index 333a1ab..6d33e9c 100644
--- a/test/script/basic/JDK-8023026.js.EXPECTED
+++ b/test/script/basic/JDK-8023026.js.EXPECTED
@@ -26,7 +26,7 @@
 reduceRight 15 1
 right sum 16
 squared 1,9,25,49
-iterating on [object Array]
+iterating on 2,4,6,8
 forEach 2
 forEach 4
 forEach 6
diff --git a/test/script/basic/JDK-8024847.js b/test/script/basic/JDK-8024847.js
index 96fdaa7..47cb3ec 100644
--- a/test/script/basic/JDK-8024847.js
+++ b/test/script/basic/JDK-8024847.js
@@ -102,7 +102,18 @@
 print(jlist);
 
 var obj = new JSObject() {
-    toNumber: function() { return 42; }
+    getMember: function(name) {
+        if (name == "valueOf") {
+            return new JSObject() {
+                isFunction: function() {
+                    return true;
+                },
+                call: function(thiz) {
+                    return 42;
+                }
+            };
+        }
+    }
 };
 
 print(32 + obj);
diff --git a/test/script/basic/JDK-8026016.js.EXPECTED b/test/script/basic/JDK-8026016.js.EXPECTED
index a2d2383..8d95d91 100644
--- a/test/script/basic/JDK-8026016.js.EXPECTED
+++ b/test/script/basic/JDK-8026016.js.EXPECTED
@@ -1,182 +1,182 @@
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-TypeError: Cannot call undefined
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such method _,0
-no such method _,1
-no such method _,2
-no such method _,3
-no such method _,4
-no such method _,5
-no such method _,6
-no such method _,7
-no such method _,8
-no such method _,9
-no such method _,10
-no such method _,11
-no such method _,12
-no such method _,13
-no such method _,14
-no such method _,15
-no such method _,16
-no such method _,17
-no such method _,18
-no such method _,19
-no such method _,20
-no such method _,21
-no such method _,22
-no such method _,23
-no such method _,24
-no such method _,25
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-TypeError: Cannot call undefined
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
-no such property _
+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+TypeError: o._ is not a function

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such method _,0

+no such method _,1

+no such method _,2

+no such method _,3

+no such method _,4

+no such method _,5

+no such method _,6

+no such method _,7

+no such method _,8

+no such method _,9

+no such method _,10

+no such method _,11

+no such method _,12

+no such method _,13

+no such method _,14

+no such method _,15

+no such method _,16

+no such method _,17

+no such method _,18

+no such method _,19

+no such method _,20

+no such method _,21

+no such method _,22

+no such method _,23

+no such method _,24

+no such method _,25

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+TypeError: o._ is not a function

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

+no such property _

diff --git a/test/script/basic/JDK-8035712.js b/test/script/basic/JDK-8035712.js
new file mode 100644
index 0000000..365ae22
--- /dev/null
+++ b/test/script/basic/JDK-8035712.js
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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-8035712: Restore some of the RuntimeCallSite specializations
+ *
+ * @test
+ * @run
+ */
+
+if ((typeof Assert) == "undefined") {
+    Assert = { 
+        assertTrue: function(x) { if(!x) { throw "expected true" } },
+        assertFalse: function(x) { if(x) { throw "expected false" } },
+    };
+}
+
+function nop() {}
+
+function EQ(x, y) {
+    // Exercise normal evaluation
+    Assert.assertTrue (x == y);
+    Assert.assertTrue (y == x);
+    Assert.assertFalse(x != y);
+    Assert.assertFalse(y != x);
+    // Exercise the branch optimizer
+    if (x == y) { nop(); } else { Assert.fail(); }
+    if (y == x) { nop(); } else { Assert.fail(); }
+    if (x != y) { Assert.fail(); } else { nop(); }
+    if (y != x) { Assert.fail(); } else { nop(); }
+}
+
+function NE(x, y) {
+    // Exercise normal evaluation
+    Assert.assertTrue (x != y);
+    Assert.assertTrue (y != x);
+    Assert.assertFalse(x == y);
+    Assert.assertFalse(y == x);
+    // Exercise the branch optimizer
+    if (x != y) { nop(); } else { Assert.fail(); }
+    if (y != x) { nop(); } else { Assert.fail(); }
+    if (x == y) { Assert.fail(); } else { nop(); }
+    if (y == x) { Assert.fail(); } else { nop(); }
+}
+
+function STRICT_EQ(x, y) {
+    // Exercise normal evaluation
+    Assert.assertTrue (x === y);
+    Assert.assertTrue (y === x);
+    Assert.assertFalse(x !== y);
+    Assert.assertFalse(y !== x);
+    // Exercise the branch optimizer
+    if (x === y) { nop(); } else { Assert.fail(); }
+    if (y === x) { nop(); } else { Assert.fail(); }
+    if (x !== y) { Assert.fail(); } else { nop(); }
+    if (y !== x) { Assert.fail(); } else { nop(); }
+}
+
+function STRICT_NE(x, y) {
+    // Exercise normal evaluation
+    Assert.assertTrue (x !== y);
+    Assert.assertTrue (y !== x);
+    Assert.assertFalse(x === y);
+    Assert.assertFalse(y === x);
+    // Exercise the branch optimizer
+    if (x !== y) { nop(); } else { Assert.fail(); }
+    if (y !== x) { nop(); } else { Assert.fail(); }
+    if (x === y) { Assert.fail(); } else { nop(); }
+    if (y === x) { Assert.fail(); } else { nop(); }
+}
+
+function cmpToAnyNumber(cmp, value) {
+    cmp(1, value);
+    cmp(4294967296, value);
+    cmp(1.2, value);
+    cmp(Infinity, value);
+    cmp(-Infinity, value);
+    cmp(1/Infinity, value);
+    cmp(0, value);
+    cmp(-0, value);
+    cmp(true, value);
+    cmp(false, value);
+}
+
+function notEqualToAnyNumber(value) {
+    cmpToAnyNumber(NE, value);
+    cmpToAnyNumber(STRICT_NE, value);
+}
+
+notEqualToAnyNumber(null);
+notEqualToAnyNumber(void 0);
+notEqualToAnyNumber("abc");
+notEqualToAnyNumber({});
+notEqualToAnyNumber(["xyz"]);
+
+function objectWithPrimitiveFunctionNotEqualToAnyNumber(fnName) {
+    var obj = {
+        count: 0
+    };
+    obj[fnName] = function() { this.count++; return "foo"; };
+    notEqualToAnyNumber(obj);
+    // Every NE will invoke it 8 times; cmpToAnyNumber has 10 comparisons
+    // STRICT_NE doesn't invoke toString.
+    Assert.assertTrue(80 === obj.count);
+}
+objectWithPrimitiveFunctionNotEqualToAnyNumber("valueOf");
+objectWithPrimitiveFunctionNotEqualToAnyNumber("toString");
+
+function objectEqualButNotStrictlyEqual(val, obj) {
+    EQ(val, obj);
+    STRICT_NE(val, obj);
+}
+
+function numberEqualButNotStrictlyEqualToObject(num, obj) {
+    objectEqualButNotStrictlyEqual(num, obj);
+    objectEqualButNotStrictlyEqual(num, [obj]);
+    objectEqualButNotStrictlyEqual(num, [[obj]]);
+}
+
+function numberEqualButNotStrictlyEqualToZeroObjects(num) {
+    numberEqualButNotStrictlyEqualToObject(num, [0]);
+    numberEqualButNotStrictlyEqualToObject(num, "");
+    numberEqualButNotStrictlyEqualToObject(num, []);
+    numberEqualButNotStrictlyEqualToObject(num, "0");
+}
+
+numberEqualButNotStrictlyEqualToZeroObjects(0);
+numberEqualButNotStrictlyEqualToZeroObjects(1/Infinity);
+numberEqualButNotStrictlyEqualToZeroObjects(false);
+
+function numberEqualButNotStrictlyEqualToObjectEquivalent(num) {
+    var str = String(num);
+    objectEqualButNotStrictlyEqual(num, str);
+    objectEqualButNotStrictlyEqual(num, { valueOf:  function() { return str }});
+    objectEqualButNotStrictlyEqual(num, { toString: function() { return str }});
+    objectEqualButNotStrictlyEqual(num, { valueOf:  function() { return num }});
+    objectEqualButNotStrictlyEqual(num, { toString: function() { return num }});
+}
+
+numberEqualButNotStrictlyEqualToObjectEquivalent(1);
+numberEqualButNotStrictlyEqualToObjectEquivalent(4294967296);
+numberEqualButNotStrictlyEqualToObjectEquivalent(1.2);
+numberEqualButNotStrictlyEqualToObjectEquivalent(Infinity);
+numberEqualButNotStrictlyEqualToObjectEquivalent(-Infinity);
+numberEqualButNotStrictlyEqualToObjectEquivalent(1/Infinity);
+numberEqualButNotStrictlyEqualToObjectEquivalent(0);
+numberEqualButNotStrictlyEqualToObjectEquivalent(-0);
+
+STRICT_EQ(1, new java.lang.Integer(1));
+STRICT_EQ(1, new java.lang.Double(1));
+STRICT_EQ(1.2, new java.lang.Double(1.2));
+
+function LE(x, y) {
+    // Exercise normal evaluation
+    Assert.assertTrue(x <= y);
+    Assert.assertTrue(y >= x);
+    Assert.assertFalse(x > y);
+    Assert.assertFalse(x < y);
+    // Exercise the branch optimizer
+    if (x <= y) { nop(); } else { Assert.fail(); }
+    if (y >= x) { nop(); } else { Assert.fail(); }
+    if (x > y) { Assert.fail(); } else { nop(); }
+    if (y < x) { Assert.fail(); } else { nop(); }
+}
+
+function mutuallyLessThanOrEqual(x, y) {
+    LE(x, y);
+    LE(y, x);
+}
+
+mutuallyLessThanOrEqual(0, null);
+mutuallyLessThanOrEqual(false, null);
+mutuallyLessThanOrEqual(1/Infinity, null);
+
+function mutuallyLessThanEqualToObjectWithValue(num, val) {
+    mutuallyLessThanOrEqual(num, { valueOf: function() { return val } });
+    mutuallyLessThanOrEqual(num, { toString: function() { return val } });
+}
+
+mutuallyLessThanEqualToObjectWithValue(false, 0);
+mutuallyLessThanEqualToObjectWithValue(false, "");
+
+mutuallyLessThanEqualToObjectWithValue(true, 1);
+mutuallyLessThanEqualToObjectWithValue(true, "1");
+
+function lessThanEqualToObjectEquivalent(num) {
+    var str = String(num);
+    mutuallyLessThanOrEqual(num, str);
+    mutuallyLessThanEqualToObjectWithValue(num, num);
+    mutuallyLessThanEqualToObjectWithValue(num, str);
+}
+
+lessThanEqualToObjectEquivalent(1);
+lessThanEqualToObjectEquivalent(4294967296);
+lessThanEqualToObjectEquivalent(1.2);
+lessThanEqualToObjectEquivalent(Infinity);
+lessThanEqualToObjectEquivalent(-Infinity);
+lessThanEqualToObjectEquivalent(1/Infinity);
+lessThanEqualToObjectEquivalent(0);
+lessThanEqualToObjectEquivalent(-0);
+
+function INCOMPARABLE(x, y) {
+    // Exercise normal evaluation
+    Assert.assertFalse(x < y);
+    Assert.assertFalse(x > y);
+    Assert.assertFalse(x <= y);
+    Assert.assertFalse(x >= y);
+    Assert.assertFalse(y < x);
+    Assert.assertFalse(y > x);
+    Assert.assertFalse(y <= x);
+    Assert.assertFalse(y >= x);
+    // Exercise the branch optimizer
+    if (x < y) { Assert.fail(); } else { nop(); }
+    if (x > y) { Assert.fail(); } else { nop(); }
+    if (x <= y) { Assert.fail(); } else { nop(); }
+    if (x >= y) { Assert.fail(); } else { nop(); }
+    if (y < x) { Assert.fail(); } else { nop(); }
+    if (y > x) { Assert.fail(); } else { nop(); }
+    if (y <= x) { Assert.fail(); } else { nop(); }
+    if (y >= x) { Assert.fail(); } else { nop(); }
+}
+
+function isIncomparable(value) {
+    cmpToAnyNumber(INCOMPARABLE, value);
+}
+
+isIncomparable(void 0);
+isIncomparable({ valueOf: function() { return NaN }});
+isIncomparable({ toString: function() { return NaN }});
+
+// Force ScriptRuntime.LT(Object, Object) etc. comparisons
+function cmpObj(fn, x, y) {
+    fn({valueOf: function() { return x }}, {valueOf: function() { return y }});
+}
+
+function LT(x, y) {
+    Assert.assertTrue(x < y);
+    Assert.assertTrue(y > x);
+    Assert.assertFalse(x >= y);
+    Assert.assertFalse(y <= x);
+}
+
+cmpObj(LT, 1, 2);
+cmpObj(LT, 1, "2");
+cmpObj(LT, "1", 2);
+cmpObj(LT, "a", "b");
+cmpObj(LT, -Infinity, 0);
+cmpObj(LT, 0, Infinity);
+cmpObj(LT, -Infinity, Infinity);
+cmpObj(INCOMPARABLE, 1, NaN);
+cmpObj(INCOMPARABLE, NaN, NaN);
+cmpObj(INCOMPARABLE, "boo", NaN);
+cmpObj(INCOMPARABLE, 1, "boo"); // boo number value will be NaN
+
+// Test that a comparison call site can deoptimize from (int, int) to (object, object)
+(function(){
+    var x = [1,  2,  "a"];
+    var y = [2, "3", "b"];
+    for(var i = 0; i < 3; ++i) {
+        Assert.assertTrue(x[i] < y[i]);
+    }
+})();
diff --git a/test/script/basic/JDK-8043232.js b/test/script/basic/JDK-8043232.js
index fa46b41..d1f3d85 100644
--- a/test/script/basic/JDK-8043232.js
+++ b/test/script/basic/JDK-8043232.js
@@ -29,14 +29,14 @@
  */
 
 // call explicit constructor
-print(new (java.awt["Color(int,int,int)"])(255,0,255));
+print(new (java.lang["String(char[],int,int)"])(['a','b', 'c', 'd'], 1, 3));
 // print the constructor itself
-print(java.awt["Color(int,int,int)"]);
+print(java.lang["String(char[],int,int)"]);
 
 // store constructor to call later
-var Color = java.awt["Color(int,int,int)"];
+var Color = java.lang["String(char[],int,int)"];
 // call stored constructor
-print(new Color(33, 233, 2))
+print(new Color(['r','r', 'e', 'd'], 1, 3))
 
 // check if default constructor works
 var obj = new (java.lang["Object()"])();
diff --git a/test/script/basic/JDK-8043232.js.EXPECTED b/test/script/basic/JDK-8043232.js.EXPECTED
index 03382ea..43d23eb 100644
--- a/test/script/basic/JDK-8043232.js.EXPECTED
+++ b/test/script/basic/JDK-8043232.js.EXPECTED
@@ -1,14 +1,28 @@
-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]
+bcd
+[jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)]
+red
 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] cannot be used as a constructor.
-TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.io.PrintStream.println] cannot 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: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod
+ String java.lang.System.getProperty(String,String)
+ String java.lang.System.getProperty(String)
+] cannot be used as a constructor.
+TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod
+ void java.io.PrintStream.println()
+ void java.io.PrintStream.println(boolean)
+ void java.io.PrintStream.println(char)
+ void java.io.PrintStream.println(char[])
+ void java.io.PrintStream.println(double)
+ void java.io.PrintStream.println(float)
+ void java.io.PrintStream.println(int)
+ void java.io.PrintStream.println(long)
+ void java.io.PrintStream.println(Object)
+ void java.io.PrintStream.println(String)
+] cannot be used as a constructor.
+TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],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/test/script/basic/JDK-8044750.js b/test/script/basic/JDK-8044750.js
index b084d57..0123fb8 100644
--- a/test/script/basic/JDK-8044750.js
+++ b/test/script/basic/JDK-8044750.js
@@ -25,6 +25,8 @@
  * JDK-8044750: megamorphic getter for scope objects does not call __noSuchProperty__ hook
  *
  * @test
+ * @fork
+ * @option -Dnashorn.unstable.relink.threshold=16
  * @run
  */
 
@@ -40,7 +42,9 @@
     }
 }
 
-for (var i = 0; i < 20; i++) {
+var LIMIT = 20; // should be more than megamorphic threshold set via @option
+
+for (var i = 0; i < LIMIT; i++) {
     var obj = {};
     obj.foo = i;
     obj[i] = i;
@@ -51,3 +55,30 @@
 // callsite inside func should see __noSuchProperty__
 // hook on global scope object.
 func({});
+
+function checkFoo() {
+    with({}) {
+        try {
+            foo;
+            return true;
+        } catch (e) {
+            return false;
+        }
+    }
+}
+
+var oldNoSuchProperty = this.__noSuchProperty__;
+delete this.__noSuchProperty__;
+
+// keep deleting/restorting __noSuchProperty__ alternatively
+// to make "foo" access in checkFoo function megamorphic!
+
+for (var i = 0; i < LIMIT; i++) {
+    // no __noSuchProperty__ and 'with' scope object has no 'foo'
+    delete __noSuchProperty__;
+    Assert.assertFalse(checkFoo(), "Expected false in iteration " + i);
+
+    // __noSuchProperty__ is exists but 'with' scope object has no 'foo'
+    this.__noSuchProperty__ = oldNoSuchProperty;
+    Assert.assertTrue(checkFoo(), "Expected true in iteration " + i);
+}
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8047365.js
similarity index 61%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8047365.js
index dfcad5a..63d0c18 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8047365.js
@@ -1,31 +1,39 @@
 /*
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8047365: Very long function names break codegen
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+// string of length 131071, twice the limit of UTF8 strings in ASM
+var longId = Array(0x20000).join("a");
+print(longId.length);
+
+eval("function " + longId + "(){ print('hello world'); }");
+eval("print(typeof " + longId + ")");
+eval("print(" + longId + ".name === longId)");
+eval("print(/a+/.exec(" + longId + ".toString())[0] === longId)");
+eval(longId + "()");
diff --git a/test/script/basic/JDK-8047365.js.EXPECTED b/test/script/basic/JDK-8047365.js.EXPECTED
new file mode 100644
index 0000000..1bb1a01
--- /dev/null
+++ b/test/script/basic/JDK-8047365.js.EXPECTED
@@ -0,0 +1,5 @@
+131071
+function
+true
+true
+hello world
diff --git a/test/script/basic/JDK-8049086.js b/test/script/basic/JDK-8049086.js
index da4a962..7dd7ac4 100644
--- a/test/script/basic/JDK-8049086.js
+++ b/test/script/basic/JDK-8049086.js
@@ -58,7 +58,7 @@
 // (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.String is java function? " + Java.isJavaFunction(java.lang.String));
 print("java.lang.Runnable instance is java function? "
     + Java.isJavaFunction(new java.lang.Runnable(function() {})));
 print("eval is java function? " + Java.isJavaFunction(eval));
diff --git a/test/script/basic/JDK-8049086.js.EXPECTED b/test/script/basic/JDK-8049086.js.EXPECTED
index d67db5d..e868572 100644
--- a/test/script/basic/JDK-8049086.js.EXPECTED
+++ b/test/script/basic/JDK-8049086.js.EXPECTED
@@ -13,7 +13,7 @@
 Object is script object? true
 {} is script object? true
 /foo/ is script object? true
-java.awt.Color is java function? true
+java.lang.String is java function? true
 java.lang.Runnable instance is java function? true
 eval is java function? false
 println is java function? true
diff --git a/test/script/basic/JDK-8049242.js b/test/script/basic/JDK-8049242.js
index 3e803b3..c44e330 100644
--- a/test/script/basic/JDK-8049242.js
+++ b/test/script/basic/JDK-8049242.js
@@ -29,14 +29,14 @@
  */
 
 // call explicit constructor
-print(new (Java.type("java.awt.Color")["(int,int,int)"])(255,0,255));
+print(new (Java.type("java.lang.String")["(char[],int,int)"])(['a', 'b', 'c'],0, 3));
 // print the constructor itself
-print(Java.type("java.awt.Color")["(int,int,int)"]);
+print(Java.type("java.lang.String")["(char[],int,int)"]);
 
 // store constructor to call later
-var Color = Java.type("java.awt.Color")["(int,int,int)"];
+var Color = Java.type("java.lang.String")["(char[],int,int)"];
 // call stored constructor
-print(new Color(33, 233, 2))
+print(new Color(['j', 'a', 'v', 'a'], 1, 3))
 
 // check if default constructor works
 var obj = new (Java.type("java.lang.Object")["()"])();
diff --git a/test/script/basic/JDK-8049242.js.EXPECTED b/test/script/basic/JDK-8049242.js.EXPECTED
index 4a2f416..f54d15b 100644
--- a/test/script/basic/JDK-8049242.js.EXPECTED
+++ b/test/script/basic/JDK-8049242.js.EXPECTED
@@ -1,10 +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]
+abc
+[jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)]
+ava
 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: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],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/test/script/basic/JDK-8051778.js b/test/script/basic/JDK-8051778.js
index 2d8d788..ef3991a 100644
--- a/test/script/basic/JDK-8051778.js
+++ b/test/script/basic/JDK-8051778.js
@@ -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.
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8053905.js
similarity index 60%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8053905.js
index dfcad5a..9d47c97 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8053905.js
@@ -1,31 +1,39 @@
 /*
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8053905: Eager code generation fails for earley boyer with split threshold set to 1000
+ *
+ * @test
+ * @runif external.octane
+ * @fork
+ * @option -Dnashorn.compiler.splitter.threshold=1000
+ * @option -Dnashorn.options.allowEagerCompilationSilentOverride
+ * @option -scripting
+ * @option --lazy-compilation=false
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+var fn  = __DIR__ + 'compile-octane.js';
+arguments.push("earley-boyer"); // run only earley-boyer
+var url = new java.io.File(fn).toURL();
+load(url);
diff --git a/test/script/basic/JDK-8053905.js.EXPECTED b/test/script/basic/JDK-8053905.js.EXPECTED
new file mode 100644
index 0000000..d8c6c88
--- /dev/null
+++ b/test/script/basic/JDK-8053905.js.EXPECTED
@@ -0,0 +1,2 @@
+Compiling 'earley-boyer'...
+Done.
diff --git a/test/script/basic/JDK-8055762.js b/test/script/basic/JDK-8055762.js
index e772a57..a0aac52 100644
--- a/test/script/basic/JDK-8055762.js
+++ b/test/script/basic/JDK-8055762.js
@@ -74,9 +74,12 @@
         }
     };
 
+    var a = "a";
     print(obj["foo"]);
+    print(obj[a + "bc"]);
     print(obj[2]);
     obj.bar = 23;
+    obj[a + "bc"] = 23;
     obj[3] = 23;
     obj.func("hello");
 }
diff --git a/test/script/basic/JDK-8055762.js.EXPECTED b/test/script/basic/JDK-8055762.js.EXPECTED
index 51a0201..1cba646 100644
--- a/test/script/basic/JDK-8055762.js.EXPECTED
+++ b/test/script/basic/JDK-8055762.js.EXPECTED
@@ -1,5 +1,7 @@
 FOO
+ABC
 0
 bar set to 23
+abc set to 23
 [3] set to 23
 func called with hello
diff --git a/test/script/basic/JDK-8058561.js b/test/script/basic/JDK-8058561.js
index f27d1d1..9f8f910 100644
--- a/test/script/basic/JDK-8058561.js
+++ b/test/script/basic/JDK-8058561.js
@@ -26,7 +26,9 @@
  *
  * @test
  * @run
+ * @fork
  * @option --lazy-compilation=false
+ * @option -Dnashorn.options.allowEagerCompilationSilentOverride
  */
 
 // Just attempting to compile this caused the NPE
diff --git a/test/script/basic/JDK-8058610.js b/test/script/basic/JDK-8058610.js
index 47078c0..08bef17 100644
--- a/test/script/basic/JDK-8058610.js
+++ b/test/script/basic/JDK-8058610.js
@@ -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.
diff --git a/test/script/basic/JDK-8061113.js b/test/script/basic/JDK-8061113.js
index 1cd8b35..b63ba4e 100644
--- a/test/script/basic/JDK-8061113.js
+++ b/test/script/basic/JDK-8061113.js
@@ -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.
diff --git a/test/script/basic/JDK-8062141.js b/test/script/basic/JDK-8062141.js
new file mode 100644
index 0000000..953d92f
--- /dev/null
+++ b/test/script/basic/JDK-8062141.js
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8062141: Various performance issues parsing JSON
+ *
+ * @test
+ * @run
+ */
+
+function testJson(json) {
+    try {
+        print(JSON.stringify(JSON.parse(json)));
+    } catch (error) {
+        print(error);
+    }
+}
+
+testJson('"\\u003f"');
+testJson('"\\u0"');
+testJson('"\\u0"');
+testJson('"\\u00"');
+testJson('"\\u003"');
+testJson('"\\u003x"');
+testJson('"\\"');
+testJson('"');
+testJson('+1');
+testJson('-1');
+testJson('1.');
+testJson('.1');
+testJson('01');
+testJson('1e');
+testJson('1e0');
+testJson('1a');
+testJson('1e+');
+testJson('1e-');
+testJson('0.0e+0');
+testJson('0.0e-0');
+testJson('[]');
+testJson('[ 1 ]');
+testJson('[1,]');
+testJson('[ 1 , 2 ]');
+testJson('[1, 2');
+testJson('{}');
+testJson('{ "a" : "b" }');
+testJson('{ "a" : "b" ');
+testJson('{ "a" : }');
+testJson('true');
+testJson('tru');
+testJson('true1');
+testJson('false');
+testJson('fals');
+testJson('falser');
+testJson('null');
+testJson('nul');
+testJson('null0');
+testJson('{} 0');
+testJson('{} a');
+testJson('[] 0');
+testJson('[] a');
+testJson('1 0');
+testJson('1 a');
+testJson('["a":true]');
+testJson('{"a",truer}');
+testJson('{"a":truer}');
+testJson('[1, 2, 3]');
+testJson('[9223372036854774000, 9223372036854775000, 9223372036854776000]');
+testJson('[1.1, 1.2, 1.3]');
+testJson('[1, 1.2, 9223372036854776000, null, true]');
+testJson('{ "a" : "string" , "b": 1 , "c" : 1.2 , "d" : 9223372036854776000 , "e" : null , "f" : true }');
+
diff --git a/test/script/basic/JDK-8062141.js.EXPECTED b/test/script/basic/JDK-8062141.js.EXPECTED
new file mode 100644
index 0000000..18dd8f4
--- /dev/null
+++ b/test/script/basic/JDK-8062141.js.EXPECTED
@@ -0,0 +1,120 @@
+"?"
+SyntaxError: Invalid JSON: <json>:1:4 Invalid hex digit
+"\u0"
+    ^
+SyntaxError: Invalid JSON: <json>:1:4 Invalid hex digit
+"\u0"
+    ^
+SyntaxError: Invalid JSON: <json>:1:5 Invalid hex digit
+"\u00"
+     ^
+SyntaxError: Invalid JSON: <json>:1:6 Invalid hex digit
+"\u003"
+      ^
+SyntaxError: Invalid JSON: <json>:1:6 Invalid hex digit
+"\u003x"
+      ^
+SyntaxError: Invalid JSON: <json>:1:3 Missing close quote
+"\"
+   ^
+SyntaxError: Invalid JSON: <json>:1:1 Missing close quote
+"
+ ^
+SyntaxError: Invalid JSON: <json>:1:0 Expected json literal but found +
++1
+^
+-1
+SyntaxError: Invalid JSON: <json>:1:2 Invalid JSON number format
+1.
+  ^
+SyntaxError: Invalid JSON: <json>:1:0 Invalid JSON number format
+.1
+^
+SyntaxError: Invalid JSON: <json>:1:1 Expected eof but found 1
+01
+ ^
+SyntaxError: Invalid JSON: <json>:1:2 Invalid JSON number format
+1e
+  ^
+1
+SyntaxError: Invalid JSON: <json>:1:1 Expected eof but found a
+1a
+ ^
+SyntaxError: Invalid JSON: <json>:1:3 Invalid JSON number format
+1e+
+   ^
+SyntaxError: Invalid JSON: <json>:1:3 Invalid JSON number format
+1e-
+   ^
+0
+0
+[]
+[1]
+SyntaxError: Invalid JSON: <json>:1:3 Trailing comma is not allowed in JSON
+[1,]
+   ^
+[1,2]
+SyntaxError: Invalid JSON: <json>:1:5 Expected , or ] but found eof
+[1, 2
+     ^
+{}
+{"a":"b"}
+SyntaxError: Invalid JSON: <json>:1:12 Expected , or } but found eof
+{ "a" : "b" 
+            ^
+SyntaxError: Invalid JSON: <json>:1:8 Expected json literal but found }
+{ "a" : }
+        ^
+true
+SyntaxError: Invalid JSON: <json>:1:0 Expected json literal but found ident
+tru
+^
+SyntaxError: Invalid JSON: <json>:1:4 Expected eof but found 1
+true1
+    ^
+false
+SyntaxError: Invalid JSON: <json>:1:0 Expected json literal but found ident
+fals
+^
+SyntaxError: Invalid JSON: <json>:1:5 Expected eof but found r
+falser
+     ^
+null
+SyntaxError: Invalid JSON: <json>:1:0 Expected json literal but found ident
+nul
+^
+SyntaxError: Invalid JSON: <json>:1:4 Expected eof but found 0
+null0
+    ^
+SyntaxError: Invalid JSON: <json>:1:3 Expected eof but found 0
+{} 0
+   ^
+SyntaxError: Invalid JSON: <json>:1:3 Expected eof but found a
+{} a
+   ^
+SyntaxError: Invalid JSON: <json>:1:3 Expected eof but found 0
+[] 0
+   ^
+SyntaxError: Invalid JSON: <json>:1:3 Expected eof but found a
+[] a
+   ^
+SyntaxError: Invalid JSON: <json>:1:2 Expected eof but found 0
+1 0
+  ^
+SyntaxError: Invalid JSON: <json>:1:2 Expected eof but found a
+1 a
+  ^
+SyntaxError: Invalid JSON: <json>:1:4 Expected , or ] but found :
+["a":true]
+    ^
+SyntaxError: Invalid JSON: <json>:1:4 Expected : but found ,
+{"a",truer}
+    ^
+SyntaxError: Invalid JSON: <json>:1:9 Expected , or } but found r
+{"a":truer}
+         ^
+[1,2,3]
+[9223372036854773800,9223372036854774800,9223372036854776000]
+[1.1,1.2,1.3]
+[1,1.2,9223372036854776000,null,true]
+{"a":"string","b":1,"c":1.2,"d":9223372036854776000,"e":null,"f":true}
diff --git a/test/script/basic/JDK-8062799.js b/test/script/basic/JDK-8062799.js
index b3af6db..9d127b5 100644
--- a/test/script/basic/JDK-8062799.js
+++ b/test/script/basic/JDK-8062799.js
@@ -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.
@@ -100,4 +100,4 @@
 
     
     
-        
\ No newline at end of file
+        
diff --git a/test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java b/test/script/basic/JDK-8066214.js
similarity index 65%
copy from test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java
copy to test/script/basic/JDK-8066214.js
index d9a4455..fbf9af3 100644
--- a/test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java
+++ b/test/script/basic/JDK-8066214.js
@@ -1,37 +1,49 @@
 /*
  * 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.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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.internal.dynalink.beans;
+/**
+ * JDK-8066214: Fuzzing bug: Object.prototype.toLocaleString(0)
+ *
+ * @test
+ * @run
+ */
 
-import jdk.nashorn.test.models.ClassLoaderAware;
-import org.testng.annotations.Test;
-
-@SuppressWarnings("javadoc")
-public class CallerSensitiveTest {
-    @Test
-    public void testCallerSensitive() {
-        BeansLinker.getLinkerForClass(ClassLoaderAware.class);
+function test(func) {
+    print(func.call(0));
+    print(func.call("abc"));
+    print(func.call(true));
+    try {
+        print(func.call(undefined));
+    } catch (e) {
+        print(e);
+    }
+    try {
+        print(func.call(null));
+    } catch (e) {
+        print(e);
     }
 }
+
+test(Object.prototype.toLocaleString);
+test(Object.prototype.toString);
+test(Object.prototype.valueOf);
diff --git a/test/script/basic/JDK-8066214.js.EXPECTED b/test/script/basic/JDK-8066214.js.EXPECTED
new file mode 100644
index 0000000..baf23ea
--- /dev/null
+++ b/test/script/basic/JDK-8066214.js.EXPECTED
@@ -0,0 +1,15 @@
+0
+abc
+true
+TypeError: undefined is not an Object
+TypeError: null is not an Object
+[object Number]
+[object String]
+[object Boolean]
+[object Undefined]
+[object Null]
+0
+abc
+true
+TypeError: undefined is not an Object
+TypeError: null is not an Object
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8066215.js
similarity index 61%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8066215.js
index dfcad5a..3987fd8 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8066215.js
@@ -1,31 +1,46 @@
 /*
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8066215: Fuzzing bug: length valueOf bug
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
+function defineLength(arr, length) {
+    Object.defineProperty(arr, "length", {
+        value: {
+            valueOf: function() {
+                print("value retrieved: " + length);
+                return length;
+            }
+        }
+    });
+    print("done: " + arr.length + ", " + typeof arr.length);
 }
+
+var a = [];
+defineLength(a, 3);
+defineLength(a, 6);
+defineLength(a, 3);
diff --git a/test/script/basic/JDK-8066215.js.EXPECTED b/test/script/basic/JDK-8066215.js.EXPECTED
new file mode 100644
index 0000000..f10edda
--- /dev/null
+++ b/test/script/basic/JDK-8066215.js.EXPECTED
@@ -0,0 +1,9 @@
+value retrieved: 3
+value retrieved: 3
+done: 3, number
+value retrieved: 6
+value retrieved: 6
+done: 6, number
+value retrieved: 3
+value retrieved: 3
+done: 3, number
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8066220.js
similarity index 66%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8066220.js
index dfcad5a..3a248a6 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8066220.js
@@ -1,31 +1,38 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ * 
  * This code is free software; you can redistribute 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.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8066220: Fuzzing bug: MethodHandle bug (Object,Object) != (boolean)Object
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+
+function f() {}
+// Call f with primitive this first, then as constructor
+f.call(1);
+new f();
+
+// Same as above in strict mode
+eval('"use strict"; function e() { print(typeof this); } e.call(1); new e();');
diff --git a/test/script/basic/JDK-8066220.js.EXPECTED b/test/script/basic/JDK-8066220.js.EXPECTED
new file mode 100644
index 0000000..0943386
--- /dev/null
+++ b/test/script/basic/JDK-8066220.js.EXPECTED
@@ -0,0 +1,2 @@
+number
+object
diff --git a/test/script/basic/JDK-8066221.js b/test/script/basic/JDK-8066221.js
index 7af4dfa..d20760a 100644
--- a/test/script/basic/JDK-8066221.js
+++ b/test/script/basic/JDK-8066221.js
@@ -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.
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8066222.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8066222.js
index dfcad5a..e86c63d 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8066222.js
@@ -1,12 +1,10 @@
 /*
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,15 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * JDK-8066222: too strong assertion on function expression names
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+// Has to print "SUCCESS"
+(function x (x){print(x)})("SUCCESS");
+
+// Has to print "undefined" and "1", not the function source in any case.
+(function x(){print(x); var x=1; print(x)})();
diff --git a/test/script/basic/JDK-8066222.js.EXPECTED b/test/script/basic/JDK-8066222.js.EXPECTED
new file mode 100644
index 0000000..5dad0b6
--- /dev/null
+++ b/test/script/basic/JDK-8066222.js.EXPECTED
@@ -0,0 +1,3 @@
+SUCCESS
+undefined
+1
diff --git a/test/script/basic/JDK-8066224.js b/test/script/basic/JDK-8066224.js
index b29ba35..2ad051b 100644
--- a/test/script/basic/JDK-8066224.js
+++ b/test/script/basic/JDK-8066224.js
@@ -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.
diff --git a/test/script/basic/JDK-8066225.js b/test/script/basic/JDK-8066225.js
index 84d56b8..10e351d 100644
--- a/test/script/basic/JDK-8066225.js
+++ b/test/script/basic/JDK-8066225.js
@@ -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.
diff --git a/test/script/basic/JDK-8066226.js b/test/script/basic/JDK-8066226.js
new file mode 100644
index 0000000..7c43da9
--- /dev/null
+++ b/test/script/basic/JDK-8066226.js
@@ -0,0 +1,132 @@
+/*
+ * 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-8066226: Fuzzing bug: parameter counts differ in TypeConverterFactory
+ *
+ * @test
+ * @run
+ */
+
+Object.defineProperty(Object.prototype, "accessor", {
+    set: function(value) {
+        print("Setting accessor on " + this + " to " + value);
+    }
+});
+
+Object.defineProperty(Object.prototype, "getterOnly", {
+    get: function() {
+        return 1;
+    }
+});
+
+function set(o) {
+    print("set(" + o + ")");
+    o.foo = 1;
+    o.constructor = 1;
+    o.accessor = 1;
+    o.getterOnly = 1;
+    print();
+}
+
+function setStrict(o) {
+    "use strict";
+    print("setStrict(" + o + ")")
+    try {
+        o.foo = 1;
+    } catch (e) {
+        print(e);
+    }
+    try {
+        o.constructor = 1;
+    } catch (e) {
+        print(e);
+    }
+    try {
+        o.accessor = 1;
+    } catch (e) {
+        print(e);
+    }
+    try {
+        o.getterOnly = 1;
+    } catch (e) {
+        print(e);
+    }
+    print();
+}
+
+function setAttr(o, id) {
+    print("setAttr(" + o + ", " + id + ")")
+    o[id] = 1;
+    print();
+}
+
+function setAttrStrict(o, id) {
+    "use strict";
+    print("setAttrStrict(" + o + ", " + id + ")")
+    try {
+        o[id] = 1;
+    } catch (e) {
+        print(e);
+    }
+    print();
+}
+
+set(1);
+set("str");
+set(true);
+set({});
+set([]);
+
+setStrict(1);
+setStrict("str");
+setStrict(true);
+setStrict({});
+setStrict([]);
+
+setAttr(1, "foo");
+setAttr(1, "constructor");
+setAttr(1, "accessor");
+setAttr(1, "getterOnly");
+setAttr("str", "foo");
+setAttr("str", "constructor");
+setAttr("str", "accessor");
+setAttr("str", "getterOnly");
+setAttr(true, "foo");
+setAttr(true, "constructor");
+setAttr(true, "accessor");
+setAttr(true, "getterOnly");
+
+setAttrStrict(1, "foo");
+setAttrStrict(1, "constructor");
+setAttrStrict(1, "accessor");
+setAttrStrict(1, "getterOnly");
+setAttrStrict("str", "foo");
+setAttrStrict("str", "constructor");
+setAttrStrict("str", "accessor");
+setAttrStrict("str", "getterOnly");
+setAttrStrict(true, "foo");
+setAttrStrict(true, "constructor");
+setAttrStrict(true, "accessor");
+setAttrStrict(true, "getterOnly");
diff --git a/test/script/basic/JDK-8066226.js.EXPECTED b/test/script/basic/JDK-8066226.js.EXPECTED
new file mode 100644
index 0000000..7c6c3e1
--- /dev/null
+++ b/test/script/basic/JDK-8066226.js.EXPECTED
@@ -0,0 +1,104 @@
+set(1)
+Setting accessor on 1 to 1
+
+set(str)
+Setting accessor on str to 1
+
+set(true)
+Setting accessor on true to 1
+
+set([object Object])
+Setting accessor on [object Object] to 1
+
+set()
+Setting accessor on  to 1
+
+setStrict(1)
+TypeError: "foo" is not a writable property of 1
+TypeError: "constructor" is not a writable property of 1
+Setting accessor on 1 to 1
+TypeError: Cannot set property "getterOnly" of [object Object] that has only a getter
+
+setStrict(str)
+TypeError: "foo" is not a writable property of str
+TypeError: "constructor" is not a writable property of str
+Setting accessor on str to 1
+TypeError: Cannot set property "getterOnly" of [object Object] that has only a getter
+
+setStrict(true)
+TypeError: "foo" is not a writable property of true
+TypeError: "constructor" is not a writable property of true
+Setting accessor on true to 1
+TypeError: Cannot set property "getterOnly" of [object Object] that has only a getter
+
+setStrict([object Object])
+Setting accessor on [object Object] to 1
+TypeError: Cannot set property "getterOnly" of [object Object] that has only a getter
+
+setStrict()
+Setting accessor on  to 1
+TypeError: Cannot set property "getterOnly" of [object Array] that has only a getter
+
+setAttr(1, foo)
+
+setAttr(1, constructor)
+
+setAttr(1, accessor)
+Setting accessor on 1 to 1
+
+setAttr(1, getterOnly)
+
+setAttr(str, foo)
+
+setAttr(str, constructor)
+
+setAttr(str, accessor)
+Setting accessor on str to 1
+
+setAttr(str, getterOnly)
+
+setAttr(true, foo)
+
+setAttr(true, constructor)
+
+setAttr(true, accessor)
+Setting accessor on true to 1
+
+setAttr(true, getterOnly)
+
+setAttrStrict(1, foo)
+TypeError: "foo" is not a writable property of 1
+
+setAttrStrict(1, constructor)
+TypeError: "constructor" is not a writable property of 1
+
+setAttrStrict(1, accessor)
+Setting accessor on 1 to 1
+
+setAttrStrict(1, getterOnly)
+TypeError: Cannot set property "getterOnly" of [object Object] that has only a getter
+
+setAttrStrict(str, foo)
+TypeError: "foo" is not a writable property of str
+
+setAttrStrict(str, constructor)
+TypeError: "constructor" is not a writable property of str
+
+setAttrStrict(str, accessor)
+Setting accessor on str to 1
+
+setAttrStrict(str, getterOnly)
+TypeError: Cannot set property "getterOnly" of [object Object] that has only a getter
+
+setAttrStrict(true, foo)
+TypeError: "foo" is not a writable property of true
+
+setAttrStrict(true, constructor)
+TypeError: "constructor" is not a writable property of true
+
+setAttrStrict(true, accessor)
+Setting accessor on true to 1
+
+setAttrStrict(true, getterOnly)
+TypeError: Cannot set property "getterOnly" of [object Object] that has only a getter
+
diff --git a/test/script/basic/JDK-8066227.js b/test/script/basic/JDK-8066227.js
index aded343..c4415da 100644
--- a/test/script/basic/JDK-8066227.js
+++ b/test/script/basic/JDK-8066227.js
@@ -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.
diff --git a/test/script/basic/JDK-8066230.js b/test/script/basic/JDK-8066230.js
index c6a3583..3586e21 100644
--- a/test/script/basic/JDK-8066230.js
+++ b/test/script/basic/JDK-8066230.js
@@ -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.
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8066232.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8066232.js
index dfcad5a..3ecd12a 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8066232.js
@@ -1,12 +1,10 @@
 /*
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,18 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * JDK-8066232: problem with conditional catch compilation
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+(function () { 
+    try {
+        x;
+    } catch(e if 1) {
+    }
+})()
+
+print("SUCCESS");
diff --git a/test/script/basic/JDK-8066232.js.EXPECTED b/test/script/basic/JDK-8066232.js.EXPECTED
new file mode 100644
index 0000000..ff43ca4
--- /dev/null
+++ b/test/script/basic/JDK-8066232.js.EXPECTED
@@ -0,0 +1 @@
+SUCCESS
diff --git a/test/script/basic/JDK-8066236.js b/test/script/basic/JDK-8066236.js
index 760e0f4..df09e63 100644
--- a/test/script/basic/JDK-8066236.js
+++ b/test/script/basic/JDK-8066236.js
@@ -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.
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8066237.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8066237.js
index dfcad5a..a06a014 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8066237.js
@@ -1,31 +1,38 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ * 
  * This code is free software; you can redistribute 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.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8066237: Fuzzing bug: Parser error on optimistic recompilation
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
+try {
+    (function() {
+        eval("get, a")
+    })();
+    fail("should have thrown");
+} catch (e) {
+    Assert.assertTrue(e.name === "ReferenceError");
 }
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8066407.js
similarity index 62%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8066407.js
index dfcad5a..bc0290f 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8066407.js
@@ -1,31 +1,48 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ * 
  * This code is free software; you can redistribute 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.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8066407: Function with same body not reparsed after SyntaxError
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
+function testFunction(body) {
+    try {
+        Function(body);
+        Assert.fail("Should have thrown");
+    } catch (e) {
+        Assert.assertEquals(e.name, "SyntaxError");
+        count++;
+    }
+
 }
+
+var count = 0;
+
+testFunction("/a/r");
+testFunction("/a/r");
+testFunction("/a/r");
+
+Assert.assertTrue(count === 3);
diff --git a/test/script/basic/JDK-8067139.js b/test/script/basic/JDK-8067139.js
new file mode 100644
index 0000000..0e66d5b
--- /dev/null
+++ b/test/script/basic/JDK-8067139.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-8067139: Finally blocks inlined incorrectly
+ *
+ * @test
+ * @run
+ */
+
+// Test case for JDK-8067139
+// as well as for JDK-8030198 which is a duplicate.
+(function(){
+    var catchCount = 0; 
+    try {
+        (function (){
+            try { 
+                return; 
+            } catch(x) { 
+                ++catchCount;
+            } finally { 
+                throw 0; 
+            } 
+        })();
+        Assert.fail(); // must throw
+    } catch(e) {
+        Assert.assertEquals(e, 0); // threw 0
+        Assert.assertEquals(catchCount, 0); // inner catch never executed
+    }
+})();
+
+// Test case for JDK-8048862 which is a duplicate of this bug
+var ret = (function(o) { 
+    try{
+        with(o) {
+            return x;
+        }
+    } finally {
+        try { 
+            return x;
+        } catch(e) {
+            Assert.assertTrue(e instanceof ReferenceError);
+            return 2;
+        }
+    }
+})({x: 1});
+Assert.assertEquals(ret, 2); // executed the catch block
+
+// Test cases for JDK-8066231 that is a duplicate of this bug
+// Case 1
+(function (){ try { Object; } catch(x if x >>>=0) { throw x2; } finally { } })();
+// Case 2
+try {
+    (function (){ try { return; } catch(x) { return x ^= 0; } finally { throw 0; } })();
+    Assert.fail();
+} catch(e) {
+    Assert.assertEquals(e, 0); // threw 0
+}
+// Case 3
+try {
+    (function (){ try { return; } catch(x) { return x ^= Object; } finally { throw Object; } })();
+    Assert.fail();
+} catch(e) {
+    Assert.assertEquals(e, Object); // threw Object
+}
+// Case from comment
+try {
+    (function () { try { Object } catch(x) { (x=y); return; } finally { throw Object; } })();
+    Assert.fail();
+} catch(e) {
+    Assert.assertEquals(e, Object); // threw Object
+}
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8067774.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8067774.js
index dfcad5a..79ad3bb 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8067774.js
@@ -1,12 +1,10 @@
 /*
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,17 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * JDK-8067774: Use a stack of types when calculating local variable types
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+print((function (p) {
+    var a, b;
+    
+    a = p ? ((b = 1), b) : 0;
+
+    return a;
+})(true));
diff --git a/test/script/basic/JDK-8067774.js.EXPECTED b/test/script/basic/JDK-8067774.js.EXPECTED
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/test/script/basic/JDK-8067774.js.EXPECTED
@@ -0,0 +1 @@
+1
diff --git a/test/script/basic/JDK-8068573.js b/test/script/basic/JDK-8068573.js
index 73f7158..ad416b1 100644
--- a/test/script/basic/JDK-8068573.js
+++ b/test/script/basic/JDK-8068573.js
@@ -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.
diff --git a/test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java b/test/script/basic/JDK-8068580.js
similarity index 61%
copy from test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java
copy to test/script/basic/JDK-8068580.js
index d9a4455..0394dea 100644
--- a/test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java
+++ b/test/script/basic/JDK-8068580.js
@@ -4,9 +4,7 @@
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,15 +21,22 @@
  * questions.
  */
 
-package jdk.internal.dynalink.beans;
+/**
+ * JDK-8068580: make JavaAdapterFactory.isAutoConvertibleFromFunction more robust
+ *
+ * @test
+ * @run
+ */
 
-import jdk.nashorn.test.models.ClassLoaderAware;
-import org.testng.annotations.Test;
-
-@SuppressWarnings("javadoc")
-public class CallerSensitiveTest {
-    @Test
-    public void testCallerSensitive() {
-        BeansLinker.getLinkerForClass(ClassLoaderAware.class);
-    }
+var BigAbstract = Java.type("jdk.nashorn.test.models.BigAbstract")
+try {
+    new BigAbstract({});
+} catch (e) {
+    Assert.assertTrue(e instanceof TypeError);
+    Assert.assertEquals(e.message, "Can not extend/implement [class jdk.nashorn.test.models.BigAbstract] because of java.lang.RuntimeException: Method code too large!");
+}
+try {
+    BigAbstract.accept(function() { });
+} catch (e) {
+    Assert.assertSame(e.class, java.lang.ClassCastException.class);
 }
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8068872.js
similarity index 66%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8068872.js
index dfcad5a..4d25ccf 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8068872.js
@@ -1,31 +1,34 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ * 
  * This code is free software; you can redistribute 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.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8068872:  Nashorn JSON.parse drops numeric keys
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+print(JSON.stringify(JSON.parse('{"3": 1, "5": "a"}')));
+print(JSON.stringify(JSON.parse('{"5": 1, "3": "a"}')));
+print(JSON.stringify(JSON.parse('{"0": 1, "4294967294": "a"}')));
+print(JSON.stringify(JSON.parse('{"4294967294": 1, "0": "a"}')));
diff --git a/test/script/basic/JDK-8068872.js.EXPECTED b/test/script/basic/JDK-8068872.js.EXPECTED
new file mode 100644
index 0000000..a191d20
--- /dev/null
+++ b/test/script/basic/JDK-8068872.js.EXPECTED
@@ -0,0 +1,4 @@
+{"3":1,"5":"a"}
+{"3":"a","5":1}
+{"0":1,"4294967294":"a"}
+{"0":"a","4294967294":1}
diff --git a/test/script/basic/JDK-8068901.js b/test/script/basic/JDK-8068901.js
new file mode 100644
index 0000000..0c24eef
--- /dev/null
+++ b/test/script/basic/JDK-8068901.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8068901: Surprising behavior with more than one functional interface on a class
+ *
+ * @test
+ * @run
+ */
+
+var Consumer = java.util.function.Consumer;
+var JFunction = java.util.function.Function;
+
+var fc = new (Java.extend(JFunction, Consumer))({
+    apply: function(x) { print("fc invoked as a function") },
+    accept: function(x) { print("fc invoked as a consumer") }
+});
+
+var c = new Consumer(function(x) { print("c invoked as a consumer") });
+
+var cf = new (Java.extend(Consumer, JFunction))({
+    apply: function(x) { print("cf invoked as a function") },
+    accept: function(x) { print("cf invoked as a consumer") }
+});
+
+var f = new JFunction(function(x) { print("f invoked as a function") });
+
+for each(x in [fc, c, fc, cf, f, cf, c, fc, f, cf]) { x(null); }
+
diff --git a/test/script/basic/JDK-8068901.js.EXPECTED b/test/script/basic/JDK-8068901.js.EXPECTED
new file mode 100644
index 0000000..edf7ff1
--- /dev/null
+++ b/test/script/basic/JDK-8068901.js.EXPECTED
@@ -0,0 +1,10 @@
+fc invoked as a function

+c invoked as a consumer

+fc invoked as a function

+cf invoked as a consumer

+f invoked as a function

+cf invoked as a consumer

+c invoked as a consumer

+fc invoked as a function

+f invoked as a function

+cf invoked as a consumer

diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8068903.js
similarity index 64%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8068903.js
index dfcad5a..8209bbb 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8068903.js
@@ -1,31 +1,40 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ * 
  * This code is free software; you can redistribute 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.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8068903: Can't invoke vararg @FunctionalInterface methods
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+var vc = new (Java.type("jdk.nashorn.test.models.VarArgConsumer"))(
+    function(x) {
+        Assert.assertTrue(x.length == 3);
+        Assert.assertTrue(x[0] == 1);
+        Assert.assertTrue(x[1] == 2);
+        Assert.assertTrue(x[2] == 3);
+    }
+);
+
+vc(1, 2, 3);
diff --git a/test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java b/test/script/basic/JDK-8068985.js
similarity index 60%
copy from test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java
copy to test/script/basic/JDK-8068985.js
index d9a4455..4b78f46 100644
--- a/test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java
+++ b/test/script/basic/JDK-8068985.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,15 +21,31 @@
  * questions.
  */
 
-package jdk.internal.dynalink.beans;
+/**
+ * JDK-8068985: Wrong 'this' bound to eval call within a function when caller's 'this' is a Java object
+ *
+ * @test
+ * @run
+ */
 
-import jdk.nashorn.test.models.ClassLoaderAware;
-import org.testng.annotations.Test;
-
-@SuppressWarnings("javadoc")
-public class CallerSensitiveTest {
-    @Test
-    public void testCallerSensitive() {
-        BeansLinker.getLinkerForClass(ClassLoaderAware.class);
-    }
+function func(arg) {
+  (function() { print(eval('this')); }).call(arg);
 }
+
+// primitives
+func(undefined);
+func(null);
+func(34.23);
+func("hello");
+func(false);
+
+// script objects
+func(this);
+func({});
+func({ toString: function() { return "foo" } });
+
+// java objects
+func(new java.util.Vector());
+var m = new java.util.HashMap();
+m.put("foo", "bar");
+func(m);
diff --git a/test/script/basic/JDK-8068985.js.EXPECTED b/test/script/basic/JDK-8068985.js.EXPECTED
new file mode 100644
index 0000000..7a218e4
--- /dev/null
+++ b/test/script/basic/JDK-8068985.js.EXPECTED
@@ -0,0 +1,10 @@
+[object global]
+[object global]
+34.23
+hello
+false
+[object global]
+[object Object]
+foo
+[]
+{foo=bar}
diff --git a/test/script/basic/JDK-8069002.js b/test/script/basic/JDK-8069002.js
index 29d7551..7788971 100644
--- a/test/script/basic/JDK-8069002.js
+++ b/test/script/basic/JDK-8069002.js
@@ -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.
diff --git a/test/script/basic/JDK-8071928.js b/test/script/basic/JDK-8071928.js
new file mode 100644
index 0000000..df9cd7a
--- /dev/null
+++ b/test/script/basic/JDK-8071928.js
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8071928: Instance properties with getters returning wrong values
+ *
+ * @test
+ * @run
+ */
+
+
+var types = {};
+
+function Type() {}
+
+Type.prototype.getName = function() {
+    return this._name;
+};
+
+function defineType(init) {
+    return Object.create(Type.prototype, {
+        _name: { get: function() { return init.name; } }
+    });
+}
+
+types.A = defineType({ name: 'A' });
+types.B = defineType({ name: 'B' });
+types.C = defineType({ name: 'C' });
+types.D = defineType({ name: 'D' });
+
+var keys = Object.keys(types);
+for (var i = 0; i < keys.length; i++) {
+    var t = types[keys[i]];
+    if (t.getName() != keys[i]) {
+        throw 'wrong name for ' + keys[i] + ': ' + t.getName();
+    }
+}
diff --git a/test/script/basic/JDK-8072426.js b/test/script/basic/JDK-8072426.js
new file mode 100644
index 0000000..03846a1
--- /dev/null
+++ b/test/script/basic/JDK-8072426.js
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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-8072426: Can't compare Java objects to strings or numbers
+ *
+ * @test
+ * @run
+ */
+
+Assert.assertTrue(java.math.RoundingMode.UP == "UP");
+
+var JSObject = Java.type("jdk.nashorn.api.scripting.JSObject");
+
+// Adds an "isFunction" member to the JSObject that returns the specified value
+function addIsFunction(isFunction, obj) {
+    obj.isFunction = function() {
+        return isFunction;
+    };
+    return obj;
+}
+
+function makeJSObjectConstantFunction(value) {
+    return new JSObject(addIsFunction(true, {
+        call: function() {
+            return value;
+        }
+    }));
+}
+
+function makeJSObjectWithMembers(mapping) {
+    return new JSObject({
+        getMember: function(name) {
+            Assert.assertTrue(mapping.hasOwnProperty(name));
+            return mapping[name];
+        },
+        toNumber: function() {
+            // toNumber no longer invoked
+            Assert.fail();
+        }
+    });
+}
+
+// Test JSObjectLinker toInt32/toLong/toNumber
+function testNumericJSObject(kind, value) {
+    var obj = makeJSObjectWithMembers({
+            valueOf: makeJSObjectConstantFunction(value)
+        });
+
+    if (kind === "double") {
+        // There's no assertEquals(double actual, double expected). There's only
+        // assertEquals(double actual, double expected, double delta).
+        Assert["assertEquals(double,double,double)"](value, obj, 0);
+    } else {
+        Assert["assertEquals(" + kind + ", " + kind + ")"](value, obj);
+    }
+    Assert.assertTrue(value == Number(obj));
+}
+testNumericJSObject("int", 42);
+testNumericJSObject("long", 4294967296);
+testNumericJSObject("double", 1.2);
+
+// Test fallback from toNumber to toString for numeric conversion when toNumber doesn't exist
+(function() {
+    var obj = makeJSObjectWithMembers({
+        valueOf:  null, // Explicitly no valueOf
+        toString: makeJSObjectConstantFunction("123")
+    });
+    Assert["assertEquals(int,int)"](123, obj);
+})();
+
+// Test fallback from toNumber to toString for numeric conversion when toNumber isn't a callable
+(function() {
+    var obj = makeJSObjectWithMembers({
+        valueOf:  new JSObject(addIsFunction(false, {})),
+        toString: makeJSObjectConstantFunction("124")
+    });
+    Assert["assertEquals(int,int)"](124, obj);
+})();
+
+// Test fallback from toNumber to toString for numeric conversion when toNumber returns a non-primitive
+(function() {
+    var obj = makeJSObjectWithMembers({
+        valueOf:  makeJSObjectConstantFunction({}),
+        toString: makeJSObjectConstantFunction("125")
+    });
+    Assert["assertEquals(int,int)"](125, obj);
+})();
+
+// Test TypeError from toNumber to toString when both return a non-primitive
+(function() {
+    var obj = makeJSObjectWithMembers({
+        valueOf:  makeJSObjectConstantFunction({}),
+        toString: makeJSObjectConstantFunction({})
+    });
+    try {
+        Number(obj);
+        Assert.fail(); // must throw
+    } catch(e) {
+        Assert.assertTrue(e instanceof TypeError); 
+    }
+})();
+
+// Test toString for string conversion
+(function() {
+    var obj = makeJSObjectWithMembers({
+        toString: makeJSObjectConstantFunction("Hello")
+    });
+    Assert.assertTrue("Hello" === String(obj));
+    Assert["assertEquals(String,String)"]("Hello", obj);
+})();
+
+// Test fallback from toString to valueOf for string conversion when toString doesn't exist
+(function() {
+    var obj = makeJSObjectWithMembers({
+        toString: null,
+        valueOf:  makeJSObjectConstantFunction("Hello1")
+    });
+    Assert.assertTrue("Hello1" === String(obj));
+    Assert["assertEquals(String,String)"]("Hello1", obj);
+})();
+
+// Test fallback from toString to valueOf for string conversion when toString is not callable
+(function() {
+    var obj = makeJSObjectWithMembers({
+        toString: new JSObject(addIsFunction(false, {})),
+        valueOf:  makeJSObjectConstantFunction("Hello2")
+    });
+    Assert["assertEquals(String,String)"]("Hello2", obj);
+})();
+
+// Test fallback from toString to valueOf for string conversion when toString returns non-primitive
+(function() {
+    var obj = makeJSObjectWithMembers({
+        toString: makeJSObjectConstantFunction({}),
+        valueOf:  makeJSObjectConstantFunction("Hello3")
+    });
+    Assert["assertEquals(String,String)"]("Hello3", obj);
+})();
+
+// Test toBoolean for JSObject
+(function() {
+    Assert["assertEquals(boolean,boolean)"](true, new JSObject({}));
+})();
diff --git a/test/script/basic/JDK-8072596.js b/test/script/basic/JDK-8072596.js
new file mode 100644
index 0000000..878824d
--- /dev/null
+++ b/test/script/basic/JDK-8072596.js
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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-8072596: Arrays.asList results in ClassCastException with a JS array
+ *
+ * @test
+ * @run
+ */
+var arr = java.util.Arrays.asList("hello world".split(' '));
+// We split it into a list of two elements: [hello, world]
+Assert.assertTrue(arr instanceof java.util.List);
+Assert.assertEquals(arr.length, 2);
+Assert.assertEquals(arr[0], "hello");
+Assert.assertEquals(arr[1], "world");
+
+var Jdk8072596TestSubject = Java.type("jdk.nashorn.test.models.Jdk8072596TestSubject");
+var testSubject = new Jdk8072596TestSubject({bar: 0});
+testSubject.test1(true, {foo: 1}, {bar: 2});
+testSubject.test2(true, {foo: 1}, {bar: 2}, {baz: 3}, {bing: 4});
+var h = "h";
+var ello = "ello";
+testSubject.test3(true, {foo: 5}, /* ConsString, why not */ h + ello, [6, 7], 8);
+Jdk8072596TestSubject.test4({foo: 9});
+
+// Test wrapping setters arguments and unwrapping getters return values on list.
+var list = new java.util.ArrayList();
+list.add(null);
+var obj0 = {valueOf: function() { return 0; }};
+var obj1 = {foo: 10};
+list[obj0] = obj1;
+testSubject.testListHasWrappedObject(list);
+// NOTE: can't use Assert.assertSame(obj1, list[obj0]), as the arguments would end up being wrapped...
+Assert.assertTrue(obj1 === list[obj0]);
+
+// Test wrapping setters arguments and unwrapping getters return values on array.
+var arr2 = new (Java.type("java.lang.Object[]"))(1);
+var obj2 = {bar: 11};
+arr2[obj0] = obj2;
+testSubject.testArrayHasWrappedObject(arr2);
+Assert.assertTrue(obj2 === arr2[obj0]);
+
+// Test wrapping setters index and arguments and getters index, and unwrapping getters return values on map.
+// Since ScriptObjectMirror.equals() uses underlying ScriptObject identity, using them as map keys works.
+var map = new java.util.HashMap();
+var obj3 = {bar: 12};
+map[obj0] = obj3;
+testSubject.testMapHasWrappedObject(map, obj0);
+Assert.assertTrue(obj3 === map[obj0]);
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8073733.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8073733.js
index dfcad5a..0d5077e 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8073733.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,29 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * JDK-8073733: TypeError messages with "call" and "new" could be improved
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
+var func = undefined;
+try {
+    func();
+} catch (e) {
+    print(e);
+}
+
+var obj = {};
+try {
+    obj.foo();
+} catch (e) {
+    print(e);
+}
+
+try {
+    new func();
+} catch (e) {
+    print(e);
 }
diff --git a/test/script/basic/JDK-8073733.js.EXPECTED b/test/script/basic/JDK-8073733.js.EXPECTED
new file mode 100644
index 0000000..22c8982
--- /dev/null
+++ b/test/script/basic/JDK-8073733.js.EXPECTED
@@ -0,0 +1,3 @@
+TypeError: func is not a function

+TypeError: obj.foo is not a function

+TypeError: func is not a function

diff --git a/test/script/basic/JDK-8073846.js b/test/script/basic/JDK-8073846.js
new file mode 100644
index 0000000..d9009c3
--- /dev/null
+++ b/test/script/basic/JDK-8073846.js
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8073846: Javascript for-in loop returned extra keys
+ *
+ * @test
+ * @run
+ */
+
+var obj = {};
+
+var list = [
+    '2100000',
+    '420000',
+    '430000'
+];
+
+for (var i = 0; i < list.length; i++) {
+    if (obj[list[i]]) print("duplicate: " + list[i]);
+    obj[list[i]] = 'obj' + list[i]
+}
+
+var count = 0;
+for (var a in obj) {
+    count++;
+    if ('obj' + a !== obj[a]) {
+        throw 'wrong key or value: ' + a + ', ' + obj[a];
+    }
+}
+
+if (count !== 3) {
+    throw 'wrong entry count: ' + count;
+}
diff --git a/test/script/basic/JDK-8073868.js b/test/script/basic/JDK-8073868.js
new file mode 100644
index 0000000..f35fb16
--- /dev/null
+++ b/test/script/basic/JDK-8073868.js
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8073868: Regex matching causes java.lang.ArrayIndexOutOfBoundsException: 64
+ *
+ * @test
+ * @run
+ */
+
+function test(input) {
+    var comma = input.indexOf(",");
+    Assert.assertEquals(/([^\s]+),(.*)+/.exec(input)[0], input.trimLeft());
+    Assert.assertEquals(/([^\s]+),(.*)+/.exec(input)[1], input.substring(0, comma).trimLeft());
+    Assert.assertEquals(/([^\s]+),(.*)+/.exec(input)[2], input.substring(comma + 1));
+    Assert.assertEquals(/(.*)+/.exec(input)[0], input);
+    Assert.assertEquals(/(.*)+/.exec(input)[1], input);
+}
+
+test(" xxxx,         xxx xxxxxx xxxxxxxxx xxxxxxx, xxxx xxxxx xxxxx ");
+test(" xxxx, xxx xxxxxx xxxxxxxxx xxxxxxx, xxxx xxxxx xxxxx ");
+test("x,         xxxxxxxxxx xxxxxxxxx xxxxxxx, xxxx xxxxx xxxxx ");
+
+Assert.assertEquals(/(?:\1a|())*/.exec("a")[0], "a");
+Assert.assertEquals(/(?:\1a|())*/.exec("a")[1], undefined);
diff --git a/test/script/basic/JDK-8074021.js b/test/script/basic/JDK-8074021.js
new file mode 100644
index 0000000..753cc78
--- /dev/null
+++ b/test/script/basic/JDK-8074021.js
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8074021: Indirect eval fails when used as an element of an array or as a property of an object
+ *
+ * @test
+ * @run
+ */
+
+var obj = { foo: eval };
+Assert.assertTrue(obj.foo("typeof(print) == 'function'"));
+Assert.assertTrue(obj.foo("RegExp instanceof Function"));
+Assert.assertEquals(obj.foo("String(new Array(2, 4, 3))"), "2,4,3");
+obj.foo("print('hello')");
+
+var args = [ eval ];
+Assert.assertTrue(args[0]("typeof(print) == 'function'"));
+Assert.assertTrue(args[0]("RegExp instanceof Function"));
+Assert.assertEquals(args[0]("String(new Array(2, 4, 3))"), "2,4,3");
+args[0]("print('hello')");
diff --git a/test/script/basic/JDK-8074021.js.EXPECTED b/test/script/basic/JDK-8074021.js.EXPECTED
new file mode 100644
index 0000000..317e967
--- /dev/null
+++ b/test/script/basic/JDK-8074021.js.EXPECTED
@@ -0,0 +1,2 @@
+hello
+hello
diff --git a/test/script/basic/JDK-8074545.js b/test/script/basic/JDK-8074545.js
new file mode 100644
index 0000000..e2ea38c
--- /dev/null
+++ b/test/script/basic/JDK-8074545.js
@@ -0,0 +1,1038 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8074545: Undefined object values in object literals with spill properties
+ *
+ * @test
+ * @run
+ */
+
+var obj = {
+    "p0": { "x" : 0 },
+    "p1": { "x" : 1 },
+    "p2": { "x" : 2 },
+    "p3": { "x" : 3 },
+    "p4": { "x" : 4 },
+    "p5": { "x" : 5 },
+    "p6": { "x" : 6 },
+    "p7": { "x" : 7 },
+    "p8": { "x" : 8 },
+    "p9": { "x" : 9 },
+    "p10": { "x" : 10 },
+    "p11": { "x" : 11 },
+    "p12": { "x" : 12 },
+    "p13": { "x" : 13 },
+    "p14": { "x" : 14 },
+    "p15": { "x" : 15 },
+    "p16": { "x" : 16 },
+    "p17": { "x" : 17 },
+    "p18": { "x" : 18 },
+    "p19": { "x" : 19 },
+    "p20": { "x" : 20 },
+    "p21": { "x" : 21 },
+    "p22": { "x" : 22 },
+    "p23": { "x" : 23 },
+    "p24": { "x" : 24 },
+    "p25": { "x" : 25 },
+    "p26": { "x" : 26 },
+    "p27": { "x" : 27 },
+    "p28": { "x" : 28 },
+    "p29": { "x" : 29 },
+    "p30": { "x" : 30 },
+    "p31": { "x" : 31 },
+    "p32": { "x" : 32 },
+    "p33": { "x" : 33 },
+    "p34": { "x" : 34 },
+    "p35": { "x" : 35 },
+    "p36": { "x" : 36 },
+    "p37": { "x" : 37 },
+    "p38": { "x" : 38 },
+    "p39": { "x" : 39 },
+    "p40": { "x" : 40 },
+    "p41": { "x" : 41 },
+    "p42": { "x" : 42 },
+    "p43": { "x" : 43 },
+    "p44": { "x" : 44 },
+    "p45": { "x" : 45 },
+    "p46": { "x" : 46 },
+    "p47": { "x" : 47 },
+    "p48": { "x" : 48 },
+    "p49": { "x" : 49 },
+    "p50": { "x" : 50 },
+    "p51": { "x" : 51 },
+    "p52": { "x" : 52 },
+    "p53": { "x" : 53 },
+    "p54": { "x" : 54 },
+    "p55": { "x" : 55 },
+    "p56": { "x" : 56 },
+    "p57": { "x" : 57 },
+    "p58": { "x" : 58 },
+    "p59": { "x" : 59 },
+    "p60": { "x" : 60 },
+    "p61": { "x" : 61 },
+    "p62": { "x" : 62 },
+    "p63": { "x" : 63 },
+    "p64": { "x" : 64 },
+    "p65": { "x" : 65 },
+    "p66": { "x" : 66 },
+    "p67": { "x" : 67 },
+    "p68": { "x" : 68 },
+    "p69": { "x" : 69 },
+    "p70": { "x" : 70 },
+    "p71": { "x" : 71 },
+    "p72": { "x" : 72 },
+    "p73": { "x" : 73 },
+    "p74": { "x" : 74 },
+    "p75": { "x" : 75 },
+    "p76": { "x" : 76 },
+    "p77": { "x" : 77 },
+    "p78": { "x" : 78 },
+    "p79": { "x" : 79 },
+    "p80": { "x" : 80 },
+    "p81": { "x" : 81 },
+    "p82": { "x" : 82 },
+    "p83": { "x" : 83 },
+    "p84": { "x" : 84 },
+    "p85": { "x" : 85 },
+    "p86": { "x" : 86 },
+    "p87": { "x" : 87 },
+    "p88": { "x" : 88 },
+    "p89": { "x" : 89 },
+    "p90": { "x" : 90 },
+    "p91": { "x" : 91 },
+    "p92": { "x" : 92 },
+    "p93": { "x" : 93 },
+    "p94": { "x" : 94 },
+    "p95": { "x" : 95 },
+    "p96": { "x" : 96 },
+    "p97": { "x" : 97 },
+    "p98": { "x" : 98 },
+    "p99": { "x" : 99 },
+    "p100": { "x" : 100 },
+    "p101": { "x" : 101 },
+    "p102": { "x" : 102 },
+    "p103": { "x" : 103 },
+    "p104": { "x" : 104 },
+    "p105": { "x" : 105 },
+    "p106": { "x" : 106 },
+    "p107": { "x" : 107 },
+    "p108": { "x" : 108 },
+    "p109": { "x" : 109 },
+    "p110": { "x" : 110 },
+    "p111": { "x" : 111 },
+    "p112": { "x" : 112 },
+    "p113": { "x" : 113 },
+    "p114": { "x" : 114 },
+    "p115": { "x" : 115 },
+    "p116": { "x" : 116 },
+    "p117": { "x" : 117 },
+    "p118": { "x" : 118 },
+    "p119": { "x" : 119 },
+    "p120": { "x" : 120 },
+    "p121": { "x" : 121 },
+    "p122": { "x" : 122 },
+    "p123": { "x" : 123 },
+    "p124": { "x" : 124 },
+    "p125": { "x" : 125 },
+    "p126": { "x" : 126 },
+    "p127": { "x" : 127 },
+    "p128": { "x" : 128 },
+    "p129": { "x" : 129 },
+    "p130": { "x" : 130 },
+    "p131": { "x" : 131 },
+    "p132": { "x" : 132 },
+    "p133": { "x" : 133 },
+    "p134": { "x" : 134 },
+    "p135": { "x" : 135 },
+    "p136": { "x" : 136 },
+    "p137": { "x" : 137 },
+    "p138": { "x" : 138 },
+    "p139": { "x" : 139 },
+    "p140": { "x" : 140 },
+    "p141": { "x" : 141 },
+    "p142": { "x" : 142 },
+    "p143": { "x" : 143 },
+    "p144": { "x" : 144 },
+    "p145": { "x" : 145 },
+    "p146": { "x" : 146 },
+    "p147": { "x" : 147 },
+    "p148": { "x" : 148 },
+    "p149": { "x" : 149 },
+    "p150": { "x" : 150 },
+    "p151": { "x" : 151 },
+    "p152": { "x" : 152 },
+    "p153": { "x" : 153 },
+    "p154": { "x" : 154 },
+    "p155": { "x" : 155 },
+    "p156": { "x" : 156 },
+    "p157": { "x" : 157 },
+    "p158": { "x" : 158 },
+    "p159": { "x" : 159 },
+    "p160": { "x" : 160 },
+    "p161": { "x" : 161 },
+    "p162": { "x" : 162 },
+    "p163": { "x" : 163 },
+    "p164": { "x" : 164 },
+    "p165": { "x" : 165 },
+    "p166": { "x" : 166 },
+    "p167": { "x" : 167 },
+    "p168": { "x" : 168 },
+    "p169": { "x" : 169 },
+    "p170": { "x" : 170 },
+    "p171": { "x" : 171 },
+    "p172": { "x" : 172 },
+    "p173": { "x" : 173 },
+    "p174": { "x" : 174 },
+    "p175": { "x" : 175 },
+    "p176": { "x" : 176 },
+    "p177": { "x" : 177 },
+    "p178": { "x" : 178 },
+    "p179": { "x" : 179 },
+    "p180": { "x" : 180 },
+    "p181": { "x" : 181 },
+    "p182": { "x" : 182 },
+    "p183": { "x" : 183 },
+    "p184": { "x" : 184 },
+    "p185": { "x" : 185 },
+    "p186": { "x" : 186 },
+    "p187": { "x" : 187 },
+    "p188": { "x" : 188 },
+    "p189": { "x" : 189 },
+    "p190": { "x" : 190 },
+    "p191": { "x" : 191 },
+    "p192": { "x" : 192 },
+    "p193": { "x" : 193 },
+    "p194": { "x" : 194 },
+    "p195": { "x" : 195 },
+    "p196": { "x" : 196 },
+    "p197": { "x" : 197 },
+    "p198": { "x" : 198 },
+    "p199": { "x" : 199 },
+    "p200": { "x" : 200 },
+    "p201": { "x" : 201 },
+    "p202": { "x" : 202 },
+    "p203": { "x" : 203 },
+    "p204": { "x" : 204 },
+    "p205": { "x" : 205 },
+    "p206": { "x" : 206 },
+    "p207": { "x" : 207 },
+    "p208": { "x" : 208 },
+    "p209": { "x" : 209 },
+    "p210": { "x" : 210 },
+    "p211": { "x" : 211 },
+    "p212": { "x" : 212 },
+    "p213": { "x" : 213 },
+    "p214": { "x" : 214 },
+    "p215": { "x" : 215 },
+    "p216": { "x" : 216 },
+    "p217": { "x" : 217 },
+    "p218": { "x" : 218 },
+    "p219": { "x" : 219 },
+    "p220": { "x" : 220 },
+    "p221": { "x" : 221 },
+    "p222": { "x" : 222 },
+    "p223": { "x" : 223 },
+    "p224": { "x" : 224 },
+    "p225": { "x" : 225 },
+    "p226": { "x" : 226 },
+    "p227": { "x" : 227 },
+    "p228": { "x" : 228 },
+    "p229": { "x" : 229 },
+    "p230": { "x" : 230 },
+    "p231": { "x" : 231 },
+    "p232": { "x" : 232 },
+    "p233": { "x" : 233 },
+    "p234": { "x" : 234 },
+    "p235": { "x" : 235 },
+    "p236": { "x" : 236 },
+    "p237": { "x" : 237 },
+    "p238": { "x" : 238 },
+    "p239": { "x" : 239 },
+    "p240": { "x" : 240 },
+    "p241": { "x" : 241 },
+    "p242": { "x" : 242 },
+    "p243": { "x" : 243 },
+    "p244": { "x" : 244 },
+    "p245": { "x" : 245 },
+    "p246": { "x" : 246 },
+    "p247": { "x" : 247 },
+    "p248": { "x" : 248 },
+    "p249": { "x" : 249 },
+    "p250": { "x" : 250 },
+    "p251": { "x" : 251 },
+    "p252": { "x" : 252 },
+    "p253": { "x" : 253 },
+    "p254": { "x" : 254 },
+    "p255": { "x" : 255 },
+    "p256": { "x" : 256 },
+    "p257": { "x" : 257 },
+    "p258": { "x" : 258 },
+    "p259": { "x" : 259 },
+    "p260": { "x" : 260 },
+    "p261": { "x" : 261 },
+    "p262": { "x" : 262 },
+    "p263": { "x" : 263 },
+    "p264": { "x" : 264 },
+    "p265": { "x" : 265 },
+    "p266": { "x" : 266 },
+    "p267": { "x" : 267 },
+    "p268": { "x" : 268 },
+    "p269": { "x" : 269 },
+    "p270": { "x" : 270 },
+    "p271": { "x" : 271 },
+    "p272": { "x" : 272 },
+    "p273": { "x" : 273 },
+    "p274": { "x" : 274 },
+    "p275": { "x" : 275 },
+    "p276": { "x" : 276 },
+    "p277": { "x" : 277 },
+    "p278": { "x" : 278 },
+    "p279": { "x" : 279 },
+    "p280": { "x" : 280 },
+    "p281": { "x" : 281 },
+    "p282": { "x" : 282 },
+    "p283": { "x" : 283 },
+    "p284": { "x" : 284 },
+    "p285": { "x" : 285 },
+    "p286": { "x" : 286 },
+    "p287": { "x" : 287 },
+    "p288": { "x" : 288 },
+    "p289": { "x" : 289 },
+    "p290": { "x" : 290 },
+    "p291": { "x" : 291 },
+    "p292": { "x" : 292 },
+    "p293": { "x" : 293 },
+    "p294": { "x" : 294 },
+    "p295": { "x" : 295 },
+    "p296": { "x" : 296 },
+    "p297": { "x" : 297 },
+    "p298": { "x" : 298 },
+    "p299": { "x" : 299 },
+    "p300": { "x" : 300 },
+    "p301": { "x" : 301 },
+    "p302": { "x" : 302 },
+    "p303": { "x" : 303 },
+    "p304": { "x" : 304 },
+    "p305": { "x" : 305 },
+    "p306": { "x" : 306 },
+    "p307": { "x" : 307 },
+    "p308": { "x" : 308 },
+    "p309": { "x" : 309 },
+    "p310": { "x" : 310 },
+    "p311": { "x" : 311 },
+    "p312": { "x" : 312 },
+    "p313": { "x" : 313 },
+    "p314": { "x" : 314 },
+    "p315": { "x" : 315 },
+    "p316": { "x" : 316 },
+    "p317": { "x" : 317 },
+    "p318": { "x" : 318 },
+    "p319": { "x" : 319 },
+    "p320": { "x" : 320 },
+    "p321": { "x" : 321 },
+    "p322": { "x" : 322 },
+    "p323": { "x" : 323 },
+    "p324": { "x" : 324 },
+    "p325": { "x" : 325 },
+    "p326": { "x" : 326 },
+    "p327": { "x" : 327 },
+    "p328": { "x" : 328 },
+    "p329": { "x" : 329 },
+    "p330": { "x" : 330 },
+    "p331": { "x" : 331 },
+    "p332": { "x" : 332 },
+    "p333": { "x" : 333 },
+    "p334": { "x" : 334 },
+    "p335": { "x" : 335 },
+    "p336": { "x" : 336 },
+    "p337": { "x" : 337 },
+    "p338": { "x" : 338 },
+    "p339": { "x" : 339 },
+    "p340": { "x" : 340 },
+    "p341": { "x" : 341 },
+    "p342": { "x" : 342 },
+    "p343": { "x" : 343 },
+    "p344": { "x" : 344 },
+    "p345": { "x" : 345 },
+    "p346": { "x" : 346 },
+    "p347": { "x" : 347 },
+    "p348": { "x" : 348 },
+    "p349": { "x" : 349 },
+    "p350": { "x" : 350 },
+    "p351": { "x" : 351 },
+    "p352": { "x" : 352 },
+    "p353": { "x" : 353 },
+    "p354": { "x" : 354 },
+    "p355": { "x" : 355 },
+    "p356": { "x" : 356 },
+    "p357": { "x" : 357 },
+    "p358": { "x" : 358 },
+    "p359": { "x" : 359 },
+    "p360": { "x" : 360 },
+    "p361": { "x" : 361 },
+    "p362": { "x" : 362 },
+    "p363": { "x" : 363 },
+    "p364": { "x" : 364 },
+    "p365": { "x" : 365 },
+    "p366": { "x" : 366 },
+    "p367": { "x" : 367 },
+    "p368": { "x" : 368 },
+    "p369": { "x" : 369 },
+    "p370": { "x" : 370 },
+    "p371": { "x" : 371 },
+    "p372": { "x" : 372 },
+    "p373": { "x" : 373 },
+    "p374": { "x" : 374 },
+    "p375": { "x" : 375 },
+    "p376": { "x" : 376 },
+    "p377": { "x" : 377 },
+    "p378": { "x" : 378 },
+    "p379": { "x" : 379 },
+    "p380": { "x" : 380 },
+    "p381": { "x" : 381 },
+    "p382": { "x" : 382 },
+    "p383": { "x" : 383 },
+    "p384": { "x" : 384 },
+    "p385": { "x" : 385 },
+    "p386": { "x" : 386 },
+    "p387": { "x" : 387 },
+    "p388": { "x" : 388 },
+    "p389": { "x" : 389 },
+    "p390": { "x" : 390 },
+    "p391": { "x" : 391 },
+    "p392": { "x" : 392 },
+    "p393": { "x" : 393 },
+    "p394": { "x" : 394 },
+    "p395": { "x" : 395 },
+    "p396": { "x" : 396 },
+    "p397": { "x" : 397 },
+    "p398": { "x" : 398 },
+    "p399": { "x" : 399 },
+    "p400": { "x" : 400 },
+    "p401": { "x" : 401 },
+    "p402": { "x" : 402 },
+    "p403": { "x" : 403 },
+    "p404": { "x" : 404 },
+    "p405": { "x" : 405 },
+    "p406": { "x" : 406 },
+    "p407": { "x" : 407 },
+    "p408": { "x" : 408 },
+    "p409": { "x" : 409 },
+    "p410": { "x" : 410 },
+    "p411": { "x" : 411 },
+    "p412": { "x" : 412 },
+    "p413": { "x" : 413 },
+    "p414": { "x" : 414 },
+    "p415": { "x" : 415 },
+    "p416": { "x" : 416 },
+    "p417": { "x" : 417 },
+    "p418": { "x" : 418 },
+    "p419": { "x" : 419 },
+    "p420": { "x" : 420 },
+    "p421": { "x" : 421 },
+    "p422": { "x" : 422 },
+    "p423": { "x" : 423 },
+    "p424": { "x" : 424 },
+    "p425": { "x" : 425 },
+    "p426": { "x" : 426 },
+    "p427": { "x" : 427 },
+    "p428": { "x" : 428 },
+    "p429": { "x" : 429 },
+    "p430": { "x" : 430 },
+    "p431": { "x" : 431 },
+    "p432": { "x" : 432 },
+    "p433": { "x" : 433 },
+    "p434": { "x" : 434 },
+    "p435": { "x" : 435 },
+    "p436": { "x" : 436 },
+    "p437": { "x" : 437 },
+    "p438": { "x" : 438 },
+    "p439": { "x" : 439 },
+    "p440": { "x" : 440 },
+    "p441": { "x" : 441 },
+    "p442": { "x" : 442 },
+    "p443": { "x" : 443 },
+    "p444": { "x" : 444 },
+    "p445": { "x" : 445 },
+    "p446": { "x" : 446 },
+    "p447": { "x" : 447 },
+    "p448": { "x" : 448 },
+    "p449": { "x" : 449 },
+    "p450": { "x" : 450 },
+    "p451": { "x" : 451 },
+    "p452": { "x" : 452 },
+    "p453": { "x" : 453 },
+    "p454": { "x" : 454 },
+    "p455": { "x" : 455 },
+    "p456": { "x" : 456 },
+    "p457": { "x" : 457 },
+    "p458": { "x" : 458 },
+    "p459": { "x" : 459 },
+    "p460": { "x" : 460 },
+    "p461": { "x" : 461 },
+    "p462": { "x" : 462 },
+    "p463": { "x" : 463 },
+    "p464": { "x" : 464 },
+    "p465": { "x" : 465 },
+    "p466": { "x" : 466 },
+    "p467": { "x" : 467 },
+    "p468": { "x" : 468 },
+    "p469": { "x" : 469 },
+    "p470": { "x" : 470 },
+    "p471": { "x" : 471 },
+    "p472": { "x" : 472 },
+    "p473": { "x" : 473 },
+    "p474": { "x" : 474 },
+    "p475": { "x" : 475 },
+    "p476": { "x" : 476 },
+    "p477": { "x" : 477 },
+    "p478": { "x" : 478 },
+    "p479": { "x" : 479 },
+    "p480": { "x" : 480 },
+    "p481": { "x" : 481 },
+    "p482": { "x" : 482 },
+    "p483": { "x" : 483 },
+    "p484": { "x" : 484 },
+    "p485": { "x" : 485 },
+    "p486": { "x" : 486 },
+    "p487": { "x" : 487 },
+    "p488": { "x" : 488 },
+    "p489": { "x" : 489 },
+    "p490": { "x" : 490 },
+    "p491": { "x" : 491 },
+    "p492": { "x" : 492 },
+    "p493": { "x" : 493 },
+    "p494": { "x" : 494 },
+    "p495": { "x" : 495 },
+    "p496": { "x" : 496 },
+    "p497": { "x" : 497 },
+    "p498": { "x" : 498 },
+    "p499": { "x" : 499 },
+    "p500": { "x" : 500 },
+    "p501": { "x" : 501 },
+    "p502": { "x" : 502 },
+    "p503": { "x" : 503 },
+    "p504": { "x" : 504 },
+    "p505": { "x" : 505 },
+    "p506": { "x" : 506 },
+    "p507": { "x" : 507 },
+    "p508": { "x" : 508 },
+    "p509": { "x" : 509 },
+    "p510": { "x" : 510 },
+    "p511": { "x" : 511 },
+    "p512": { "x" : 512 },
+    "p513": { "x" : 513 },
+    "p514": { "x" : 514 },
+    "p515": { "x" : 515 },
+    "p516": { "x" : 516 },
+    "p517": { "x" : 517 },
+    "p518": { "x" : 518 },
+    "p519": { "x" : 519 },
+    "p520": { "x" : 520 },
+    "p521": { "x" : 521 },
+    "p522": { "x" : 522 },
+    "p523": { "x" : 523 },
+    "p524": { "x" : 524 },
+    "p525": { "x" : 525 },
+    "p526": { "x" : 526 },
+    "p527": { "x" : 527 },
+    "p528": { "x" : 528 },
+    "p529": { "x" : 529 },
+    "p530": { "x" : 530 },
+    "p531": { "x" : 531 },
+    "p532": { "x" : 532 },
+    "p533": { "x" : 533 },
+    "p534": { "x" : 534 },
+    "p535": { "x" : 535 },
+    "p536": { "x" : 536 },
+    "p537": { "x" : 537 },
+    "p538": { "x" : 538 },
+    "p539": { "x" : 539 },
+    "p540": { "x" : 540 },
+    "p541": { "x" : 541 },
+    "p542": { "x" : 542 },
+    "p543": { "x" : 543 },
+    "p544": { "x" : 544 },
+    "p545": { "x" : 545 },
+    "p546": { "x" : 546 },
+    "p547": { "x" : 547 },
+    "p548": { "x" : 548 },
+    "p549": { "x" : 549 },
+    "p550": { "x" : 550 },
+    "p551": { "x" : 551 },
+    "p552": { "x" : 552 },
+    "p553": { "x" : 553 },
+    "p554": { "x" : 554 },
+    "p555": { "x" : 555 },
+    "p556": { "x" : 556 },
+    "p557": { "x" : 557 },
+    "p558": { "x" : 558 },
+    "p559": { "x" : 559 },
+    "p560": { "x" : 560 },
+    "p561": { "x" : 561 },
+    "p562": { "x" : 562 },
+    "p563": { "x" : 563 },
+    "p564": { "x" : 564 },
+    "p565": { "x" : 565 },
+    "p566": { "x" : 566 },
+    "p567": { "x" : 567 },
+    "p568": { "x" : 568 },
+    "p569": { "x" : 569 },
+    "p570": { "x" : 570 },
+    "p571": { "x" : 571 },
+    "p572": { "x" : 572 },
+    "p573": { "x" : 573 },
+    "p574": { "x" : 574 },
+    "p575": { "x" : 575 },
+    "p576": { "x" : 576 },
+    "p577": { "x" : 577 },
+    "p578": { "x" : 578 },
+    "p579": { "x" : 579 },
+    "p580": { "x" : 580 },
+    "p581": { "x" : 581 },
+    "p582": { "x" : 582 },
+    "p583": { "x" : 583 },
+    "p584": { "x" : 584 },
+    "p585": { "x" : 585 },
+    "p586": { "x" : 586 },
+    "p587": { "x" : 587 },
+    "p588": { "x" : 588 },
+    "p589": { "x" : 589 },
+    "p590": { "x" : 590 },
+    "p591": { "x" : 591 },
+    "p592": { "x" : 592 },
+    "p593": { "x" : 593 },
+    "p594": { "x" : 594 },
+    "p595": { "x" : 595 },
+    "p596": { "x" : 596 },
+    "p597": { "x" : 597 },
+    "p598": { "x" : 598 },
+    "p599": { "x" : 599 },
+    "p600": { "x" : 600 },
+    "p601": { "x" : 601 },
+    "p602": { "x" : 602 },
+    "p603": { "x" : 603 },
+    "p604": { "x" : 604 },
+    "p605": { "x" : 605 },
+    "p606": { "x" : 606 },
+    "p607": { "x" : 607 },
+    "p608": { "x" : 608 },
+    "p609": { "x" : 609 },
+    "p610": { "x" : 610 },
+    "p611": { "x" : 611 },
+    "p612": { "x" : 612 },
+    "p613": { "x" : 613 },
+    "p614": { "x" : 614 },
+    "p615": { "x" : 615 },
+    "p616": { "x" : 616 },
+    "p617": { "x" : 617 },
+    "p618": { "x" : 618 },
+    "p619": { "x" : 619 },
+    "p620": { "x" : 620 },
+    "p621": { "x" : 621 },
+    "p622": { "x" : 622 },
+    "p623": { "x" : 623 },
+    "p624": { "x" : 624 },
+    "p625": { "x" : 625 },
+    "p626": { "x" : 626 },
+    "p627": { "x" : 627 },
+    "p628": { "x" : 628 },
+    "p629": { "x" : 629 },
+    "p630": { "x" : 630 },
+    "p631": { "x" : 631 },
+    "p632": { "x" : 632 },
+    "p633": { "x" : 633 },
+    "p634": { "x" : 634 },
+    "p635": { "x" : 635 },
+    "p636": { "x" : 636 },
+    "p637": { "x" : 637 },
+    "p638": { "x" : 638 },
+    "p639": { "x" : 639 },
+    "p640": { "x" : 640 },
+    "p641": { "x" : 641 },
+    "p642": { "x" : 642 },
+    "p643": { "x" : 643 },
+    "p644": { "x" : 644 },
+    "p645": { "x" : 645 },
+    "p646": { "x" : 646 },
+    "p647": { "x" : 647 },
+    "p648": { "x" : 648 },
+    "p649": { "x" : 649 },
+    "p650": { "x" : 650 },
+    "p651": { "x" : 651 },
+    "p652": { "x" : 652 },
+    "p653": { "x" : 653 },
+    "p654": { "x" : 654 },
+    "p655": { "x" : 655 },
+    "p656": { "x" : 656 },
+    "p657": { "x" : 657 },
+    "p658": { "x" : 658 },
+    "p659": { "x" : 659 },
+    "p660": { "x" : 660 },
+    "p661": { "x" : 661 },
+    "p662": { "x" : 662 },
+    "p663": { "x" : 663 },
+    "p664": { "x" : 664 },
+    "p665": { "x" : 665 },
+    "p666": { "x" : 666 },
+    "p667": { "x" : 667 },
+    "p668": { "x" : 668 },
+    "p669": { "x" : 669 },
+    "p670": { "x" : 670 },
+    "p671": { "x" : 671 },
+    "p672": { "x" : 672 },
+    "p673": { "x" : 673 },
+    "p674": { "x" : 674 },
+    "p675": { "x" : 675 },
+    "p676": { "x" : 676 },
+    "p677": { "x" : 677 },
+    "p678": { "x" : 678 },
+    "p679": { "x" : 679 },
+    "p680": { "x" : 680 },
+    "p681": { "x" : 681 },
+    "p682": { "x" : 682 },
+    "p683": { "x" : 683 },
+    "p684": { "x" : 684 },
+    "p685": { "x" : 685 },
+    "p686": { "x" : 686 },
+    "p687": { "x" : 687 },
+    "p688": { "x" : 688 },
+    "p689": { "x" : 689 },
+    "p690": { "x" : 690 },
+    "p691": { "x" : 691 },
+    "p692": { "x" : 692 },
+    "p693": { "x" : 693 },
+    "p694": { "x" : 694 },
+    "p695": { "x" : 695 },
+    "p696": { "x" : 696 },
+    "p697": { "x" : 697 },
+    "p698": { "x" : 698 },
+    "p699": { "x" : 699 },
+    "p700": { "x" : 700 },
+    "p701": { "x" : 701 },
+    "p702": { "x" : 702 },
+    "p703": { "x" : 703 },
+    "p704": { "x" : 704 },
+    "p705": { "x" : 705 },
+    "p706": { "x" : 706 },
+    "p707": { "x" : 707 },
+    "p708": { "x" : 708 },
+    "p709": { "x" : 709 },
+    "p710": { "x" : 710 },
+    "p711": { "x" : 711 },
+    "p712": { "x" : 712 },
+    "p713": { "x" : 713 },
+    "p714": { "x" : 714 },
+    "p715": { "x" : 715 },
+    "p716": { "x" : 716 },
+    "p717": { "x" : 717 },
+    "p718": { "x" : 718 },
+    "p719": { "x" : 719 },
+    "p720": { "x" : 720 },
+    "p721": { "x" : 721 },
+    "p722": { "x" : 722 },
+    "p723": { "x" : 723 },
+    "p724": { "x" : 724 },
+    "p725": { "x" : 725 },
+    "p726": { "x" : 726 },
+    "p727": { "x" : 727 },
+    "p728": { "x" : 728 },
+    "p729": { "x" : 729 },
+    "p730": { "x" : 730 },
+    "p731": { "x" : 731 },
+    "p732": { "x" : 732 },
+    "p733": { "x" : 733 },
+    "p734": { "x" : 734 },
+    "p735": { "x" : 735 },
+    "p736": { "x" : 736 },
+    "p737": { "x" : 737 },
+    "p738": { "x" : 738 },
+    "p739": { "x" : 739 },
+    "p740": { "x" : 740 },
+    "p741": { "x" : 741 },
+    "p742": { "x" : 742 },
+    "p743": { "x" : 743 },
+    "p744": { "x" : 744 },
+    "p745": { "x" : 745 },
+    "p746": { "x" : 746 },
+    "p747": { "x" : 747 },
+    "p748": { "x" : 748 },
+    "p749": { "x" : 749 },
+    "p750": { "x" : 750 },
+    "p751": { "x" : 751 },
+    "p752": { "x" : 752 },
+    "p753": { "x" : 753 },
+    "p754": { "x" : 754 },
+    "p755": { "x" : 755 },
+    "p756": { "x" : 756 },
+    "p757": { "x" : 757 },
+    "p758": { "x" : 758 },
+    "p759": { "x" : 759 },
+    "p760": { "x" : 760 },
+    "p761": { "x" : 761 },
+    "p762": { "x" : 762 },
+    "p763": { "x" : 763 },
+    "p764": { "x" : 764 },
+    "p765": { "x" : 765 },
+    "p766": { "x" : 766 },
+    "p767": { "x" : 767 },
+    "p768": { "x" : 768 },
+    "p769": { "x" : 769 },
+    "p770": { "x" : 770 },
+    "p771": { "x" : 771 },
+    "p772": { "x" : 772 },
+    "p773": { "x" : 773 },
+    "p774": { "x" : 774 },
+    "p775": { "x" : 775 },
+    "p776": { "x" : 776 },
+    "p777": { "x" : 777 },
+    "p778": { "x" : 778 },
+    "p779": { "x" : 779 },
+    "p780": { "x" : 780 },
+    "p781": { "x" : 781 },
+    "p782": { "x" : 782 },
+    "p783": { "x" : 783 },
+    "p784": { "x" : 784 },
+    "p785": { "x" : 785 },
+    "p786": { "x" : 786 },
+    "p787": { "x" : 787 },
+    "p788": { "x" : 788 },
+    "p789": { "x" : 789 },
+    "p790": { "x" : 790 },
+    "p791": { "x" : 791 },
+    "p792": { "x" : 792 },
+    "p793": { "x" : 793 },
+    "p794": { "x" : 794 },
+    "p795": { "x" : 795 },
+    "p796": { "x" : 796 },
+    "p797": { "x" : 797 },
+    "p798": { "x" : 798 },
+    "p799": { "x" : 799 },
+    "p800": { "x" : 800 },
+    "p801": { "x" : 801 },
+    "p802": { "x" : 802 },
+    "p803": { "x" : 803 },
+    "p804": { "x" : 804 },
+    "p805": { "x" : 805 },
+    "p806": { "x" : 806 },
+    "p807": { "x" : 807 },
+    "p808": { "x" : 808 },
+    "p809": { "x" : 809 },
+    "p810": { "x" : 810 },
+    "p811": { "x" : 811 },
+    "p812": { "x" : 812 },
+    "p813": { "x" : 813 },
+    "p814": { "x" : 814 },
+    "p815": { "x" : 815 },
+    "p816": { "x" : 816 },
+    "p817": { "x" : 817 },
+    "p818": { "x" : 818 },
+    "p819": { "x" : 819 },
+    "p820": { "x" : 820 },
+    "p821": { "x" : 821 },
+    "p822": { "x" : 822 },
+    "p823": { "x" : 823 },
+    "p824": { "x" : 824 },
+    "p825": { "x" : 825 },
+    "p826": { "x" : 826 },
+    "p827": { "x" : 827 },
+    "p828": { "x" : 828 },
+    "p829": { "x" : 829 },
+    "p830": { "x" : 830 },
+    "p831": { "x" : 831 },
+    "p832": { "x" : 832 },
+    "p833": { "x" : 833 },
+    "p834": { "x" : 834 },
+    "p835": { "x" : 835 },
+    "p836": { "x" : 836 },
+    "p837": { "x" : 837 },
+    "p838": { "x" : 838 },
+    "p839": { "x" : 839 },
+    "p840": { "x" : 840 },
+    "p841": { "x" : 841 },
+    "p842": { "x" : 842 },
+    "p843": { "x" : 843 },
+    "p844": { "x" : 844 },
+    "p845": { "x" : 845 },
+    "p846": { "x" : 846 },
+    "p847": { "x" : 847 },
+    "p848": { "x" : 848 },
+    "p849": { "x" : 849 },
+    "p850": { "x" : 850 },
+    "p851": { "x" : 851 },
+    "p852": { "x" : 852 },
+    "p853": { "x" : 853 },
+    "p854": { "x" : 854 },
+    "p855": { "x" : 855 },
+    "p856": { "x" : 856 },
+    "p857": { "x" : 857 },
+    "p858": { "x" : 858 },
+    "p859": { "x" : 859 },
+    "p860": { "x" : 860 },
+    "p861": { "x" : 861 },
+    "p862": { "x" : 862 },
+    "p863": { "x" : 863 },
+    "p864": { "x" : 864 },
+    "p865": { "x" : 865 },
+    "p866": { "x" : 866 },
+    "p867": { "x" : 867 },
+    "p868": { "x" : 868 },
+    "p869": { "x" : 869 },
+    "p870": { "x" : 870 },
+    "p871": { "x" : 871 },
+    "p872": { "x" : 872 },
+    "p873": { "x" : 873 },
+    "p874": { "x" : 874 },
+    "p875": { "x" : 875 },
+    "p876": { "x" : 876 },
+    "p877": { "x" : 877 },
+    "p878": { "x" : 878 },
+    "p879": { "x" : 879 },
+    "p880": { "x" : 880 },
+    "p881": { "x" : 881 },
+    "p882": { "x" : 882 },
+    "p883": { "x" : 883 },
+    "p884": { "x" : 884 },
+    "p885": { "x" : 885 },
+    "p886": { "x" : 886 },
+    "p887": { "x" : 887 },
+    "p888": { "x" : 888 },
+    "p889": { "x" : 889 },
+    "p890": { "x" : 890 },
+    "p891": { "x" : 891 },
+    "p892": { "x" : 892 },
+    "p893": { "x" : 893 },
+    "p894": { "x" : 894 },
+    "p895": { "x" : 895 },
+    "p896": { "x" : 896 },
+    "p897": { "x" : 897 },
+    "p898": { "x" : 898 },
+    "p899": { "x" : 899 },
+    "p900": { "x" : 900 },
+    "p901": { "x" : 901 },
+    "p902": { "x" : 902 },
+    "p903": { "x" : 903 },
+    "p904": { "x" : 904 },
+    "p905": { "x" : 905 },
+    "p906": { "x" : 906 },
+    "p907": { "x" : 907 },
+    "p908": { "x" : 908 },
+    "p909": { "x" : 909 },
+    "p910": { "x" : 910 },
+    "p911": { "x" : 911 },
+    "p912": { "x" : 912 },
+    "p913": { "x" : 913 },
+    "p914": { "x" : 914 },
+    "p915": { "x" : 915 },
+    "p916": { "x" : 916 },
+    "p917": { "x" : 917 },
+    "p918": { "x" : 918 },
+    "p919": { "x" : 919 },
+    "p920": { "x" : 920 },
+    "p921": { "x" : 921 },
+    "p922": { "x" : 922 },
+    "p923": { "x" : 923 },
+    "p924": { "x" : 924 },
+    "p925": { "x" : 925 },
+    "p926": { "x" : 926 },
+    "p927": { "x" : 927 },
+    "p928": { "x" : 928 },
+    "p929": { "x" : 929 },
+    "p930": { "x" : 930 },
+    "p931": { "x" : 931 },
+    "p932": { "x" : 932 },
+    "p933": { "x" : 933 },
+    "p934": { "x" : 934 },
+    "p935": { "x" : 935 },
+    "p936": { "x" : 936 },
+    "p937": { "x" : 937 },
+    "p938": { "x" : 938 },
+    "p939": { "x" : 939 },
+    "p940": { "x" : 940 },
+    "p941": { "x" : 941 },
+    "p942": { "x" : 942 },
+    "p943": { "x" : 943 },
+    "p944": { "x" : 944 },
+    "p945": { "x" : 945 },
+    "p946": { "x" : 946 },
+    "p947": { "x" : 947 },
+    "p948": { "x" : 948 },
+    "p949": { "x" : 949 },
+    "p950": { "x" : 950 },
+    "p951": { "x" : 951 },
+    "p952": { "x" : 952 },
+    "p953": { "x" : 953 },
+    "p954": { "x" : 954 },
+    "p955": { "x" : 955 },
+    "p956": { "x" : 956 },
+    "p957": { "x" : 957 },
+    "p958": { "x" : 958 },
+    "p959": { "x" : 959 },
+    "p960": { "x" : 960 },
+    "p961": { "x" : 961 },
+    "p962": { "x" : 962 },
+    "p963": { "x" : 963 },
+    "p964": { "x" : 964 },
+    "p965": { "x" : 965 },
+    "p966": { "x" : 966 },
+    "p967": { "x" : 967 },
+    "p968": { "x" : 968 },
+    "p969": { "x" : 969 },
+    "p970": { "x" : 970 },
+    "p971": { "x" : 971 },
+    "p972": { "x" : 972 },
+    "p973": { "x" : 973 },
+    "p974": { "x" : 974 },
+    "p975": { "x" : 975 },
+    "p976": { "x" : 976 },
+    "p977": { "x" : 977 },
+    "p978": { "x" : 978 },
+    "p979": { "x" : 979 },
+    "p980": { "x" : 980 },
+    "p981": { "x" : 981 },
+    "p982": { "x" : 982 },
+    "p983": { "x" : 983 },
+    "p984": { "x" : 984 },
+    "p985": { "x" : 985 },
+    "p986": { "x" : 986 },
+    "p987": { "x" : 987 },
+    "p988": { "x" : 988 },
+    "p989": { "x" : 989 },
+    "p990": { "x" : 990 },
+    "p991": { "x" : 991 },
+    "p992": { "x" : 992 },
+    "p993": { "x" : 993 },
+    "p994": { "x" : 994 },
+    "p995": { "x" : 995 },
+    "p996": { "x" : 996 },
+    "p997": { "x" : 997 },
+    "p998": { "x" : 998 },
+    "p999": { "x" : 999 }
+};
+
+for (var i = 0; i < 1000; i++) {
+    var value = obj["p" + i];
+    Assert.assertTrue(typeof value === "object");
+    Assert.assertTrue(value.x === i);
+}
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8074556.js
similarity index 61%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8074556.js
index dfcad5a..e3fb0d9 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8074556.js
@@ -1,31 +1,52 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ * 
  * This code is free software; you can redistribute 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.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8074556: Functions should not share allocator maps
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
+function A () {
+    return this;
 }
+
+function B() {
+    return this;
+}
+
+A.prototype.x = "x";
+A.prototype.y = "y";
+B.prototype.y = "y";  // same properties but different order
+B.prototype.x = "x";
+
+function test(o) {
+    Assert.assertEquals(o.x, "x");
+    Assert.assertEquals(o.y, "y");
+}
+
+test(new A());
+test(new B());
+test(new A());
+test(new B());
diff --git a/test/script/basic/JDK-8074687.js b/test/script/basic/JDK-8074687.js
new file mode 100644
index 0000000..9f67b24
--- /dev/null
+++ b/test/script/basic/JDK-8074687.js
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8074687:  Add tests for JSON parsing of numeric keys
+ *
+ * @test
+ * @run
+ */
+
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": {} }')),                   '{"0":{}}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": 1 }')),                    '{"0":1}');
+
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "65503": {} }')),               '{"65503":{}}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "65503": 1 }')),                '{"65503":1}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": {}, "65503": {} }')),      '{"0":{},"65503":{}}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": 1, "65503": 1 }')),        '{"0":1,"65503":1}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "65503": {}, "0": {} }')),      '{"0":{},"65503":{}}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "65503": 1, "0": 1 }')),        '{"0":1,"65503":1}');
+
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "4294967295": {} }')),          '{"4294967295":{}}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "4294967295": 1 }')),           '{"4294967295":1}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": {}, "4294967295": {} }')), '{"0":{},"4294967295":{}}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": 1, "4294967295": 1 }')),   '{"0":1,"4294967295":1}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "4294967295": {}, "0": {} }')), '{"0":{},"4294967295":{}}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "4294967295": 1, "0": 1 }')),   '{"0":1,"4294967295":1}');
+
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "100": {} }')),                 '{"100":{}}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "100": 1 }')),                  '{"100":1}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": {}, "100": {} }')),        '{"0":{},"100":{}}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": 1, "100": 1 }')),          '{"0":1,"100":1}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "100": {}, "0": {} }')),        '{"0":{},"100":{}}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "100": 1, "0": 1 }')),          '{"0":1,"100":1}');
+
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "-100": {} }')),                '{"-100":{}}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "-100": 1 }')),                 '{"-100":1}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": {}, "-100": {} }')),       '{"0":{},"-100":{}}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "0": 1, "-100": 1 }')),         '{"0":1,"-100":1}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "-100": {}, "0": {} }')),       '{"0":{},"-100":{}}');
+Assert.assertEquals(JSON.stringify(JSON.parse('{ "-100": 1, "0": 1 }')),         '{"0":1,"-100":1}');
diff --git a/test/script/basic/JDK-8074693.js b/test/script/basic/JDK-8074693.js
new file mode 100644
index 0000000..111f21c
--- /dev/null
+++ b/test/script/basic/JDK-8074693.js
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8074693: Different instances of same function use same allocator map
+ *
+ * @test
+ * @run
+ */
+
+var lib = {};
+
+lib.mixin = function(target, source) {
+    for (var p in source) {
+        if (source.hasOwnProperty(p) && !target.hasOwnProperty(p)) {
+            target.prototype[p] = source[p];
+        }
+    }
+};
+
+lib.declare = function(def) {
+    var className = def.name;
+
+    lib[className] = function() {
+        this.init.apply(this, arguments);
+    };
+
+    lib.mixin(lib[className], def.members);
+};
+
+
+lib.declare({
+    name: "ClassA",
+    members: {
+        init : function () {
+            print("init A called");
+        }
+    }
+});
+
+lib.declare({
+    name: "ClassB",
+    members: {
+        util : function () {
+            print("util called")
+        },
+        init : function() {
+            print("init B called");
+        }
+    }
+});
+
+var objA = new lib.ClassA();
+var objB = new lib.ClassB();
diff --git a/test/script/basic/JDK-8074693.js.EXPECTED b/test/script/basic/JDK-8074693.js.EXPECTED
new file mode 100644
index 0000000..42fb74c
--- /dev/null
+++ b/test/script/basic/JDK-8074693.js.EXPECTED
@@ -0,0 +1,2 @@
+init A called
+init B called
diff --git a/test/script/basic/JDK-8075090.js b/test/script/basic/JDK-8075090.js
new file mode 100644
index 0000000..eec0a55
--- /dev/null
+++ b/test/script/basic/JDK-8075090.js
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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-8075090: Add tests for the basic failure of try/finally compilation
+ *
+ * @test
+ * @run
+ */
+
+(function() {
+    var finallyExpected = false;
+    try {
+        for(var i = 0; i < 2; ++i) {
+            if(i == 1) {
+                continue;
+            }
+        }
+        finallyExpected = true;
+    } finally {
+        Assert.assertTrue(finallyExpected);
+    }
+})();
+
+(function() {
+    var finallyExpected = false;
+    try {
+        for(var i = 0; i < 2; ++i) {
+            if(i == 1) {
+                break;
+            }
+        }
+        finallyExpected = true;
+    } finally {
+        Assert.assertTrue(finallyExpected);
+    }
+})();
+
+(function() {
+    var finallyExpected = false;
+    try {
+        L1: {
+            if ((function(){return true})()) {
+                break L1;
+            }
+            Assert.fail(); // unreachable
+        }
+        finallyExpected = true;
+    } finally {
+        Assert.assertTrue(finallyExpected);
+    }
+})();
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8075927.js
similarity index 62%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8075927.js
index dfcad5a..e596fb0 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8075927.js
@@ -1,31 +1,38 @@
 /*
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8075927: toNumber(String) accepts illegal characters
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+Assert.assertTrue(isNaN(Number("-123d")));
+Assert.assertTrue(isNaN(Number("-123f")));
+Assert.assertTrue(Number("   123 ") === 123);
+Assert.assertTrue(Number("  -123 ") === -123);
+Assert.assertEquals(Number("  Infinity  "), Infinity);
+Assert.assertEquals(Number(" +Infinity  "), Infinity);
+Assert.assertEquals(Number(" -Infinity  "), -Infinity);
+
diff --git a/test/script/basic/JDK-8077955.js b/test/script/basic/JDK-8077955.js
new file mode 100644
index 0000000..31c4468
--- /dev/null
+++ b/test/script/basic/JDK-8077955.js
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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-8077955: Undeclared globals in eval code should not be handled as fast scope
+ *
+ * @test
+ * @run
+ * @fork
+ * @option -Dnashorn.fields.objects
+ */
+
+var m = new javax.script.ScriptEngineManager();
+var e = m.getEngineByName('js');
+
+// leave the whitespace - need both eval("e") at same column for this test!
+
+e.eval('function f(e) {            eval("e") } f()');
+e.eval('function f() { var e = 33; eval("e") } f()');
+
+function f() {
+    Function.call.call(function x() { eval("x") }); eval("x")
+}
+
+try {
+    f();
+    fail("Should have thrown ReferenceError");
+} catch (e) {
+    if (! (e instanceof ReferenceError)) {
+        fail("ReferenceError expected but got " + e);
+    }
+}
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8078612_eager_1a.js
similarity index 65%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8078612_eager_1a.js
index dfcad5a..1ff5a65 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8078612_eager_1a.js
@@ -1,31 +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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8078612: Persistent code cache should support more configurations
+ *
+ * @test
+ * @runif external.prototype
+ * @option -pcc
+ * @option --lazy-compilation=false
+ * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @option -Dnashorn.options.allowEagerCompilationSilentOverride
+ * @fork
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+load(__DIR__ + 'prototype.js');
diff --git a/test/script/basic/JDK-8078612_eager_1a.js.EXPECTED b/test/script/basic/JDK-8078612_eager_1a.js.EXPECTED
new file mode 100644
index 0000000..e677550
--- /dev/null
+++ b/test/script/basic/JDK-8078612_eager_1a.js.EXPECTED
@@ -0,0 +1 @@
+parsed and compiled ok prototype.js
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8078612_eager_1b.js
similarity index 65%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8078612_eager_1b.js
index dfcad5a..1ff5a65 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8078612_eager_1b.js
@@ -1,31 +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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8078612: Persistent code cache should support more configurations
+ *
+ * @test
+ * @runif external.prototype
+ * @option -pcc
+ * @option --lazy-compilation=false
+ * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @option -Dnashorn.options.allowEagerCompilationSilentOverride
+ * @fork
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+load(__DIR__ + 'prototype.js');
diff --git a/test/script/basic/JDK-8078612_eager_1b.js.EXPECTED b/test/script/basic/JDK-8078612_eager_1b.js.EXPECTED
new file mode 100644
index 0000000..e677550
--- /dev/null
+++ b/test/script/basic/JDK-8078612_eager_1b.js.EXPECTED
@@ -0,0 +1 @@
+parsed and compiled ok prototype.js
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8078612_eager_2a.js
similarity index 66%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8078612_eager_2a.js
index dfcad5a..5915efc 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8078612_eager_2a.js
@@ -1,31 +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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8078612: Persistent code cache should support more configurations
+ *
+ * @test
+ * @runif external.yui
+ * @option -pcc
+ * @option --lazy-compilation=false
+ * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @option -Dnashorn.options.allowEagerCompilationSilentOverride
+ * @fork
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+load(__DIR__ + 'yui.js');
diff --git a/test/script/basic/JDK-8078612_eager_2a.js.EXPECTED b/test/script/basic/JDK-8078612_eager_2a.js.EXPECTED
new file mode 100644
index 0000000..28dd1b9
--- /dev/null
+++ b/test/script/basic/JDK-8078612_eager_2a.js.EXPECTED
@@ -0,0 +1,2 @@
+parsed and compiled ok yui-min.js
+parsed and compiled ok yui.js
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8078612_eager_2b.js
similarity index 66%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8078612_eager_2b.js
index dfcad5a..5915efc 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8078612_eager_2b.js
@@ -1,31 +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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8078612: Persistent code cache should support more configurations
+ *
+ * @test
+ * @runif external.yui
+ * @option -pcc
+ * @option --lazy-compilation=false
+ * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @option -Dnashorn.options.allowEagerCompilationSilentOverride
+ * @fork
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+load(__DIR__ + 'yui.js');
diff --git a/test/script/basic/JDK-8078612_eager_2b.js.EXPECTED b/test/script/basic/JDK-8078612_eager_2b.js.EXPECTED
new file mode 100644
index 0000000..28dd1b9
--- /dev/null
+++ b/test/script/basic/JDK-8078612_eager_2b.js.EXPECTED
@@ -0,0 +1,2 @@
+parsed and compiled ok yui-min.js
+parsed and compiled ok yui.js
diff --git a/test/script/basic/JDK-8079145.js b/test/script/basic/JDK-8079145.js
new file mode 100644
index 0000000..29371b4
--- /dev/null
+++ b/test/script/basic/JDK-8079145.js
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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-8079145: jdk.nashorn.internal.runtime.arrays.IntArrayData.convert assertion
+ *
+ * @test
+ * @fork
+ * @option -Dnashorn.debug=true
+ * @run
+ */
+
+var Byte = java.lang.Byte;
+var Short = java.lang.Short;
+var Integer = java.lang.Integer;
+var Long = java.lang.Long;
+var Float = java.lang.Float;
+var Double = java.lang.Double;
+var Character = java.lang.Character;
+
+function checkWiden(arr, value, name) {
+    switch (typeof value) {
+    case 'object':
+    case 'undefined':
+        print(name + ": check widen for " + value);
+        break;
+    default:
+        print(name + ": check widen for " + value + 
+            " [" + Debug.getClass(value) + "]");
+    }
+
+    arr[0] = value;
+}
+
+function checkIntWiden(value) {
+   checkWiden([34], value, "int array");
+}
+
+function checkLongWiden(value) {
+    checkWiden([Integer.MAX_VALUE + 1], value, "long array");
+}
+
+function checkNumberWiden(value) {
+    checkWiden([Math.PI], value, "number array");
+}
+
+function checkObjectWiden(value) {
+    checkWiden([null], value, "object array");
+}
+
+var values = [{}, null, undefined, false, true, new Byte(34),
+   new Integer(344454), new Long(454545), new Long(Integer.MAX_VALUE + 1),
+   new Float(34.3), new Double(Math.PI), new Character('s')];
+
+for each (var v in values) {
+    checkIntWiden(v);
+}
+
+for each (var v in values) {
+    checkLongWiden(v);
+}
+
+for each (var v in values) {
+    checkNumberWiden(v);
+}
+
+for each (var v in values) {
+    checkObjectWiden(v);
+}
diff --git a/test/script/basic/JDK-8079145.js.EXPECTED b/test/script/basic/JDK-8079145.js.EXPECTED
new file mode 100644
index 0000000..6b84c5e
--- /dev/null
+++ b/test/script/basic/JDK-8079145.js.EXPECTED
@@ -0,0 +1,48 @@
+int array: check widen for [object Object]
+int array: check widen for null
+int array: check widen for undefined
+int array: check widen for false [class java.lang.Boolean]
+int array: check widen for true [class java.lang.Boolean]
+int array: check widen for 34 [class java.lang.Byte]
+int array: check widen for 344454 [class java.lang.Integer]
+int array: check widen for 454545 [class java.lang.Long]
+int array: check widen for 2147483648 [class java.lang.Long]
+int array: check widen for 34.29999923706055 [class java.lang.Float]
+int array: check widen for 3.141592653589793 [class java.lang.Double]
+int array: check widen for s
+long array: check widen for [object Object]
+long array: check widen for null
+long array: check widen for undefined
+long array: check widen for false [class java.lang.Boolean]
+long array: check widen for true [class java.lang.Boolean]
+long array: check widen for 34 [class java.lang.Byte]
+long array: check widen for 344454 [class java.lang.Integer]
+long array: check widen for 454545 [class java.lang.Long]
+long array: check widen for 2147483648 [class java.lang.Long]
+long array: check widen for 34.29999923706055 [class java.lang.Float]
+long array: check widen for 3.141592653589793 [class java.lang.Double]
+long array: check widen for s
+number array: check widen for [object Object]
+number array: check widen for null
+number array: check widen for undefined
+number array: check widen for false [class java.lang.Boolean]
+number array: check widen for true [class java.lang.Boolean]
+number array: check widen for 34 [class java.lang.Byte]
+number array: check widen for 344454 [class java.lang.Integer]
+number array: check widen for 454545 [class java.lang.Long]
+number array: check widen for 2147483648 [class java.lang.Long]
+number array: check widen for 34.29999923706055 [class java.lang.Float]
+number array: check widen for 3.141592653589793 [class java.lang.Double]
+number array: check widen for s
+object array: check widen for [object Object]
+object array: check widen for null
+object array: check widen for undefined
+object array: check widen for false [class java.lang.Boolean]
+object array: check widen for true [class java.lang.Boolean]
+object array: check widen for 34 [class java.lang.Byte]
+object array: check widen for 344454 [class java.lang.Integer]
+object array: check widen for 454545 [class java.lang.Long]
+object array: check widen for 2147483648 [class java.lang.Long]
+object array: check widen for 34.29999923706055 [class java.lang.Float]
+object array: check widen for 3.141592653589793 [class java.lang.Double]
+object array: check widen for s
diff --git a/test/script/basic/JDK-8079269.js b/test/script/basic/JDK-8079269.js
new file mode 100644
index 0000000..124ae95
--- /dev/null
+++ b/test/script/basic/JDK-8079269.js
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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-8079269: Optimistic rewrite in object literal causes ArrayIndexOutOfBoundsException
+ *
+ * @test
+ * @run
+ */
+
+// m must be in scope so it's accessed with optimistic getters on scope
+var m = 1; 
+
+(function() {
+    return { 
+        p0: m, 
+        p1: m = "foo",
+        p2: m
+    }
+})();
+
+var n = 1; 
+
+// Test the spill object creator too
+(function() {
+    return { 
+        p0: n, 
+        p1: n = "foo",
+        p2: n,
+        p3: n,
+        p4: n,
+        p5: n,
+        p6: n,
+        p7: n,
+        p8: n,
+        p9: n,
+        p10: n,
+        p11: n,
+        p12: n,
+        p13: n,
+        p14: n,
+        p15: n,
+        p16: n,
+        p17: n,
+        p18: n,
+        p19: n,
+        p20: n,
+        p21: n,
+        p22: n,
+        p23: n,
+        p24: n,
+        p25: n,
+        p26: n,
+        p27: n,
+        p28: n,
+        p29: n,
+        p30: n,
+        p31: n,
+        p32: n,
+        p33: n,
+        p34: n,
+        p35: n,
+        p36: n,
+        p37: n,
+        p38: n,
+        p39: n,
+        p40: n,
+        p41: n,
+        p42: n,
+        p43: n,
+        p44: n,
+        p45: n,
+        p46: n,
+        p47: n,
+        p48: n,
+        p49: n,
+        p50: n,
+        p51: n,
+        p52: n,
+        p53: n,
+        p54: n,
+        p55: n,
+        p56: n,
+        p57: n,
+        p58: n,
+        p59: n,
+        p60: n,
+        p61: n,
+        p62: n,
+        p63: n,
+        p64: n,
+        p65: n,
+        p66: n,
+        p67: n,
+        p68: n,
+        p69: n,
+        p70: n,
+        p71: n,
+        p72: n,
+        p73: n,
+        p74: n,
+        p75: n,
+        p76: n,
+        p77: n,
+        p78: n,
+        p79: n,
+        p80: n,
+        p81: n,
+        p82: n,
+        p83: n,
+        p84: n,
+        p85: n,
+        p86: n,
+        p87: n,
+        p88: n,
+        p89: n,
+        p90: n,
+        p91: n,
+        p92: n,
+        p93: n,
+        p94: n,
+        p95: n,
+        p96: n,
+        p97: n,
+        p98: n,
+        p99: n,
+        p100: n,
+        p101: n,
+        p102: n,
+        p103: n,
+        p104: n,
+        p105: n,
+        p106: n,
+        p107: n,
+        p108: n,
+        p109: n,
+        p110: n,
+        p111: n,
+        p112: n,
+        p113: n,
+        p114: n,
+        p115: n,
+        p116: n,
+        p117: n,
+        p118: n,
+        p119: n,
+        p120: n,
+        p121: n,
+        p122: n,
+        p123: n,
+        p124: n,
+        p125: n,
+        p126: n,
+        p127: n,
+        p128: n,
+        p129: n,
+        p130: n,
+        p131: n,
+        p132: n,
+        p133: n,
+        p134: n,
+        p135: n,
+        p136: n,
+        p137: n,
+        p138: n,
+        p139: n,
+        p140: n,
+        p141: n,
+        p142: n,
+        p143: n,
+        p144: n,
+        p145: n,
+        p146: n,
+        p147: n,
+        p148: n,
+        p149: n,
+        p150: n,
+        p151: n,
+        p152: n,
+        p153: n,
+        p154: n,
+        p155: n,
+        p156: n,
+        p157: n,
+        p158: n,
+        p159: n,
+        p160: n,
+        p161: n,
+        p162: n,
+        p163: n,
+        p164: n,
+        p165: n,
+        p166: n,
+        p167: n,
+        p168: n,
+        p169: n,
+        p170: n,
+        p171: n,
+        p172: n,
+        p173: n,
+        p174: n,
+        p175: n,
+        p176: n,
+        p177: n,
+        p178: n,
+        p179: n,
+        p180: n,
+        p181: n,
+        p182: n,
+        p183: n,
+        p184: n,
+        p185: n,
+        p186: n,
+        p187: n,
+        p188: n,
+        p189: n,
+        p190: n,
+        p191: n,
+        p192: n,
+        p193: n,
+        p194: n,
+        p195: n,
+        p196: n,
+        p197: n,
+        p198: n,
+        p199: n,
+        p200: n,
+        p201: n,
+        p202: n,
+        p203: n,
+        p204: n,
+        p205: n,
+        p206: n,
+        p207: n,
+        p208: n,
+        p209: n,
+        p210: n,
+        p211: n,
+        p212: n,
+        p213: n,
+        p214: n,
+        p215: n,
+        p216: n,
+        p217: n,
+        p218: n,
+        p219: n,
+        p220: n,
+        p221: n,
+        p222: n,
+        p223: n,
+        p224: n,
+        p225: n,
+        p226: n,
+        p227: n,
+        p228: n,
+        p229: n,
+        p230: n,
+        p231: n,
+        p232: n,
+        p233: n,
+        p234: n,
+        p235: n,
+        p236: n,
+        p237: n,
+        p238: n,
+        p239: n,
+        p240: n,
+        p241: n,
+        p242: n,
+        p243: n,
+        p244: n,
+        p245: n,
+        p246: n,
+        p247: n,
+        p248: n,
+        p249: n,
+        p250: n,
+        p251: n,
+        p252: n,
+        p253: n,
+        p254: n,
+        p255: n,
+        p256: n,
+        p257: n,
+        p258: n,
+        p259: n
+    }
+})();
+
+// No output; as long as it completes without
+// ArrayIndexOutOfBoundsException in the OSR continuation handler, it's
+// a success.
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8079424.js
similarity index 60%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8079424.js
index dfcad5a..725fe23 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8079424.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,30 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * JDK-8079424: code generator for discarded boolean logical operation has an extra pop
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+// If the compiler manages to compile all of these, the test passes.
+void (true && true);
+void (true && false);
+void (false && true);
+void (false && false);
+
+void (true || true);
+void (true || false);
+void (false || true);
+void (false || false);
+
+void (1 && 1);
+void (1 && 0);
+void (0 && 1);
+void (0 && 0);
+
+void (1 || 1);
+void (1 || 0);
+void (0 || 1);
+void (0 || 0);
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8079470.js
similarity index 65%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8079470.js
index dfcad5a..b5df13d 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8079470.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,24 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * JDK-8079470: Misleading error message when explicit signature constructor is called with wrong arguments
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
+
+var File = Java.type("java.io.File");
+try {
+    var f = new File['(String,String)']();
+} catch (e) {
+    print(e);
+}
+
+var Color = java.awt["Color(int,int,int)"]
+try {
+    var c = new Color(255, 255)
+} catch (e) {
+    print(e);
 }
diff --git a/test/script/basic/JDK-8079470.js.EXPECTED b/test/script/basic/JDK-8079470.js.EXPECTED
new file mode 100644
index 0000000..8be1c42
--- /dev/null
+++ b/test/script/basic/JDK-8079470.js.EXPECTED
@@ -0,0 +1,2 @@
+TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.io.File(String,String)] with the passed arguments; they do not match any of its method signatures.
+TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.awt.Color(int,int,int)] with the passed arguments; they do not match any of its method signatures.
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8080182.js
similarity index 63%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8080182.js
index dfcad5a..a3d1369 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8080182.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,26 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * JDK-8080182: Array.prototype.sort throws IAE on inconsistent comparison
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
+function Random() { 
+    this.toString = function() {
+        return (Math.random() * 100).toString();
+    }
+}
+
+for (var i = 0; i < 100; ++i) {
+    var arr = []; 
+
+    for (var j = 0; j < 64; ++j) {
+        arr[j] = new Random();
+    }
+
+    // no IllegalArgumentException expected!
+    arr.sort();
 }
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8080848.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8080848.js
index dfcad5a..5c22647 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8080848.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,17 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * JDK-8080848: delete of bound Java method property results in crash
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
+var obj = Object.bindProperties({}, new java.io.File("."));
+
+delete obj.wait;
+
+if (typeof obj.wait != 'undefined') {
+    throw new Error("obj.wait was not deleted");
 }
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8081156.js
similarity index 60%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8081156.js
index dfcad5a..5300f7b 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8081156.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,26 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * JDK-8081156: jjs "nashorn.args" system property is not effective when script arguments are passed
+ *
+ * @test
+ * @fork
+ * @option -Dnashorn.args=-strict
+ * @argument foo
+ * @argument bar
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
+try {
+   x = 14;
+   throw new Error("should have thrown ReferenceError");
+} catch (e) {
+   if (! (e instanceof ReferenceError)) {
+       throw e;
+   }
 }
+
+Assert.assertTrue(arguments.length == 2);
+Assert.assertTrue(arguments[0] == "foo");
+Assert.assertTrue(arguments[1] == "bar");
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8085802.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8085802.js
index dfcad5a..b6cf8d3 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8085802.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,15 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * JDK-8085802: Nashorn -nse option causes parse error on anonymous function definition
+ *
+ * @test
+ * @run
+ * @option -nse
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+// even with -nse passed, the following should run fine
+// because anonymous function is used as expression here
+
+(function (){})()
diff --git a/test/script/basic/JDK-8087211.js b/test/script/basic/JDK-8087211.js
new file mode 100644
index 0000000..49016e9
--- /dev/null
+++ b/test/script/basic/JDK-8087211.js
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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-8087211: Indirect evals should be strict with -strict option
+ *
+ * @test
+ * @run
+ * @option -strict
+ */
+
+var global = this;
+
+try {
+    // indirect eval call.
+    global.eval("x = 34;");
+    throw new Error("should have thrown ReferenceError");
+} catch (e if e instanceof ReferenceError) {
+}
+
+
+function teststrict() {
+    "use strict";
+    // strict caller, indirect eval.
+    global.eval('public = 1;');
+}
+
+try {
+    teststrict();
+    throw new Error("should have thrown SyntaxError");
+} catch (e if e instanceof SyntaxError) {
+}
+
+function testnonstrict() {
+    // non strict caller, indirect eval.
+    global.eval('public = 1;');
+}
+
+try {
+    testnonstrict();
+    throw new Error("should have thrown SyntaxError");
+} catch (e if e instanceof SyntaxError) {
+}
diff --git a/test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java b/test/script/basic/JDK-8087211_2.js
similarity index 61%
copy from test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java
copy to test/script/basic/JDK-8087211_2.js
index d9a4455..936c8b9 100644
--- a/test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java
+++ b/test/script/basic/JDK-8087211_2.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,15 +21,30 @@
  * questions.
  */
 
-package jdk.internal.dynalink.beans;
+/**
+ * JDK-8087211: Indirect evals should be strict with -strict option
+ * Make sure without -strict option, indirect evals are not strict.
+ *
+ * @test
+ * @run
+ */
 
-import jdk.nashorn.test.models.ClassLoaderAware;
-import org.testng.annotations.Test;
+var global = this;
 
-@SuppressWarnings("javadoc")
-public class CallerSensitiveTest {
-    @Test
-    public void testCallerSensitive() {
-        BeansLinker.getLinkerForClass(ClassLoaderAware.class);
-    }
+// indirect eval call.
+global.eval("x = 34;");
+
+function teststrict() {
+    "use strict";
+    // strict caller, indirect eval.
+    global.eval('public = 1;');
 }
+
+teststrict();
+
+function testnonstrict() {
+    // non strict caller, indirect eval.
+    global.eval('public = 1;');
+}
+
+testnonstrict();
diff --git a/test/script/basic/JDK-8087312.js b/test/script/basic/JDK-8087312.js
new file mode 100644
index 0000000..e009660
--- /dev/null
+++ b/test/script/basic/JDK-8087312.js
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8087312: PropertyMapWrapper.equals should compare className
+ *
+ * @test
+ * @run
+ * @fork
+ * @option -Dnashorn.debug=true
+ */
+
+function createObject(type) {
+    // we want to make sure two different object literals with the same keys and types share the same property map.
+    if (type) {
+        return {
+            a: "a",
+            b: 1,
+            c: 0.1
+        }
+    } else {
+        return {
+            a: "x",
+            b: 10,
+            c: 3.4
+        }
+    }
+}
+
+var o1 = createObject(false);
+var o2 = createObject(true);
+Assert.assertTrue(Debug.map(o1) === Debug.map(o2));
+
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8098546.js
similarity index 64%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8098546.js
index dfcad5a..1bd8470 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8098546.js
@@ -1,31 +1,44 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ * 
  * This code is free software; you can redistribute 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.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8098546: eval within a 'with' leaks definitions into global scope
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
+function func() {
+    var obj = { foo: 344 };
+    with (obj) {
+       eval("var x = foo + 3");
+    }
+    Assert.assertTrue(obj.x === undefined);
+    Assert.assertTrue(x === 347);
 }
+
+func();
+
+// x should be undefined here
+Assert.assertTrue(typeof x === "undefined");
+
diff --git a/test/script/basic/JDK-8098578.js b/test/script/basic/JDK-8098578.js
new file mode 100644
index 0000000..59e4a80
--- /dev/null
+++ b/test/script/basic/JDK-8098578.js
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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-8098578: Global scope is not accessible with indirect load call
+ *
+ * @test
+ * @run
+ */
+
+var obj = { foo: 343 };
+var global = this;
+var x = 434;
+
+// indirect load call
+var res = load.call(obj, {
+   name: "t.js",
+   // global is accessible. All declarations go into
+   // intermediate inaccessible scope. "this" is global
+   // User's passed object's properties are accessible
+   // as variables.
+   script: "foo -= 300; var bar = x; Assert.assertTrue(bar == 434); function func() {}; this"
+})
+
+// 'this' for the evaluated code is global
+Assert.assertTrue(res === global);
+
+// properties of passed object are accessible in evaluated code
+Assert.assertTrue(obj.foo == 43);
+
+// vars, functions definined in evaluated code don't go into passed object
+Assert.assertTrue(typeof obj.bar == "undefined");
+Assert.assertTrue(typeof obj.func == "undefined");
+
+// vars, functions definined in evaluated code don't go leak into global
+Assert.assertTrue(typeof bar == "undefined");
+Assert.assertTrue(typeof func == "undefined");
+Assert.assertTrue(typeof foo == "undefined");
+
+var res = load.call(undefined, {
+    name: "t1.js",
+    // still global is accessible and 'this' is global
+    script: "Assert.assertTrue(x == 434); this"
+});
+
+// indirect load with 'undefined' this is same as as direct load
+// or load on global itself.
+Assert.assertTrue(res === global);
+
+// indirect load with 'undefined' this is same as as direct load
+// or load on global itself.
+var res = load.call(null, {
+    name: "t2.js",
+    // still global is accessible and 'this' is global
+    script: "Assert.assertTrue(x == 434); this"
+});
+Assert.assertTrue(res === global);
+
+// indirect load with mirror object
+var mirror = loadWithNewGlobal({
+    name: "t3.js",
+    script: "({ foo: 'hello', x: Math.PI })"
+});
+
+var res = load.call(mirror, {
+    name: "t4.js",
+    script: "Assert.assertTrue(foo == 'hello'); Assert.assertTrue(x == Math.PI); this"
+});
+Assert.assertTrue(res === global);
+
+// indirect load on non-script object, non-mirror results in TypeError
+function tryLoad(obj) {
+    try {
+        load.call(obj, {
+            name: "t5.js", script: "this"
+        });
+        throw new Error("should thrown TypeError for: " + obj);
+    } catch (e if TypeError) {}
+}
+
+tryLoad("hello");
+tryLoad(Math.E);
+tryLoad(true);
+tryLoad(false);
+
+// indirect load of a large script
+load.call({}, __DIR__ + "JDK-8098807-payload.js");
diff --git a/test/script/basic/JDK-8098807-payload.js b/test/script/basic/JDK-8098807-payload.js
new file mode 100644
index 0000000..edfcba4
--- /dev/null
+++ b/test/script/basic/JDK-8098807-payload.js
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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-8098807:  Strict eval throws ClassCastException with large scripts
+ *
+ * @subtest
+ */
+
+function f() {}
+
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
+f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f(); f();
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8098807.js
similarity index 67%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8098807.js
index dfcad5a..f73b6bb 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8098807.js
@@ -1,31 +1,36 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ * 
  * This code is free software; you can redistribute 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.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8098807:  Strict eval throws ClassCastException with large scripts
+ *
+ * @test
+ * @run
+ * @option -scripting
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+"use strict";
+
+var path = __DIR__ + "JDK-8098807-payload.js"
+var source = readFully(path);
+eval(source);
diff --git a/test/script/basic/JDK-8114838.js b/test/script/basic/JDK-8114838.js
new file mode 100644
index 0000000..7a2420a
--- /dev/null
+++ b/test/script/basic/JDK-8114838.js
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8114838: Anonymous functions escape to surrounding scope when defined under "with" statement
+ *
+ * @test
+ * @run
+ */
+
+// do *not* introduce new lines! The next line should be 32
+with({}) { function () {} }
+if (typeof this["L:32"] != 'undefined') {
+    throw new Error("anonymous name spills into global scope");
+}
+
+var func = eval("function() {}");
+if (typeof func != 'function') {
+    throw new Error("eval of anonymous function does not work!");
+}
+
+var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager");
+var engine = new ScriptEngineManager().getEngineByName("nashorn");
+var func2 = engine.eval("function() {}");
+if (typeof func2 != 'function') {
+    throw new Error("eval of anonymous function does not work from script engine!");
+}
diff --git a/test/script/basic/JDK-8129410.js b/test/script/basic/JDK-8129410.js
new file mode 100644
index 0000000..19d2799
--- /dev/null
+++ b/test/script/basic/JDK-8129410.js
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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-8129410: Java adapters with class-level overrides should preserve variable arity constructors
+ *
+ * @test
+ * @run
+ */
+
+var VarArgConstructor = Java.type("jdk.nashorn.test.models.VarArgConstructor");
+var VarArgConstructorExtended = Java.extend(VarArgConstructor, {});
+
+// If the fix didn't work we wouldn't even get past the constructor invocation
+// as it'd complain there's no matching arity constructor.
+var newExtended = new VarArgConstructorExtended(1, true, "a", "b");
+
+// Assert the expected constructor was invoked.
+Assert.assertEquals("vararg", newExtended.indicator);
diff --git a/test/script/basic/JDK-8130853.js b/test/script/basic/JDK-8130853.js
new file mode 100644
index 0000000..872cf72
--- /dev/null
+++ b/test/script/basic/JDK-8130853.js
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8130853: Non-extensible global is not handled property
+ *
+ * @test
+ * @run
+ */
+
+// don't allow extensions to global
+Object.preventExtensions(this);
+try {
+    eval("var x = 34;");
+    throw new Error("should have thrown TypeError");
+} catch (e) {
+    if (! (e instanceof TypeError)) {
+        throw e;
+    }
+}
+
+try {
+    eval("function func() {}");
+    throw new Error("should have thrown TypeError");
+} catch (e) {
+    if (! (e instanceof TypeError)) {
+        throw e;
+    }
+}
+
+function checkLoad(code) {
+    try {
+        load({ name: "test", script: code });
+        throw new Error("should have thrown TypeError for load: " + code);
+    } catch (e) {
+        if (! (e instanceof TypeError)) {
+            throw e;
+        }
+    }
+}
+
+checkLoad("var y = 55");
+checkLoad("function f() {}");
+
+// check script engine eval
+var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager");
+var e = new ScriptEngineManager().getEngineByName("nashorn");
+var global = e.eval("this");
+e.eval("Object.preventExtensions(this);");
+try {
+    e.eval("var myVar = 33;");
+    throw new Error("should have thrown TypeError");
+} catch (e) {
+    if (! (e.cause.ecmaError instanceof global.TypeError)) {
+        throw e;
+    }
+}
+
+// Object.bindProperties on arbitrary non-extensible object
+var obj = {};
+Object.preventExtensions(obj);
+try {
+    Object.bindProperties(obj, { foo: 434 });
+    throw new Error("should have thrown TypeError");
+} catch (e) {
+    if (! (e instanceof TypeError)) {
+        throw e;
+    }
+}
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8131039.js
similarity index 65%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8131039.js
index dfcad5a..9bcd13f 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8131039.js
@@ -1,31 +1,35 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ * 
  * This code is free software; you can redistribute 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.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8131039: after adding a function property to Object.prototype, JSON.parse with reviver function goes into infinite loop
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+Object.prototype.func = function() {}
+
+function identity(k, v) { return v };
+var obj = JSON.parse('{\"name\" : \"nashorn\"}', identity);
+Assert.assertTrue(obj.name, "nashorn");
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8131340.js
similarity index 64%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8131340.js
index dfcad5a..bcdd749 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8131340.js
@@ -1,31 +1,43 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ * 
  * This code is free software; you can redistribute 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.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8131340:  Varargs function is recompiled each time it is linked
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
+// This is an indirect test. If repeated calls were to cause recompilation
+// this would trigger an assertion in RecompilableScriptFunctionData.
+
+function varargs() {
+    return arguments;
 }
+
+varargs(1);
+varargs(2);
+varargs(3);
+varargs(4);
+varargs(5);
+varargs(6);
diff --git a/test/script/basic/JDK-8131683.js b/test/script/basic/JDK-8131683.js
new file mode 100644
index 0000000..3159662
--- /dev/null
+++ b/test/script/basic/JDK-8131683.js
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8131683: Delete fails over multiple scopes
+ *
+ * @test
+ * @run
+ */
+
+a = 1;
+b = 2;
+c = 3;
+
+var A = 1;
+var B = 2;
+var C = 3;
+function D() {}
+
+print((function() {
+    var x; // force creation of scope
+    (function() { x; })();
+    return delete a;
+})());
+
+print((function() {
+    eval("");
+    return delete b;
+})());
+
+print((function() {
+    return eval("delete c");
+})());
+
+print((function() {
+    eval("d = 4");
+    return eval("delete d");
+})());
+
+print(typeof a);
+print(typeof b);
+print(typeof c);
+print(typeof d);
+
+print((function() {
+    var x; // force creation of scope
+    (function() { x; })();
+    return delete A;
+})());
+
+print((function() {
+    eval("");
+    return delete B;
+})());
+
+print((function() {
+    return eval("delete C");
+})());
+
+print((function() {
+    eval("");
+    return delete D;
+})());
+
+print(typeof A);
+print(typeof B);
+print(typeof C);
+print(typeof D);
+
diff --git a/test/script/basic/JDK-8131683.js.EXPECTED b/test/script/basic/JDK-8131683.js.EXPECTED
new file mode 100644
index 0000000..d1fbed7
--- /dev/null
+++ b/test/script/basic/JDK-8131683.js.EXPECTED
@@ -0,0 +1,16 @@
+true
+true
+true
+true
+undefined
+undefined
+undefined
+undefined
+false
+false
+false
+false
+number
+number
+number
+function
diff --git a/test/script/basic/JDK-8133119.js b/test/script/basic/JDK-8133119.js
new file mode 100644
index 0000000..4a0e5a5
--- /dev/null
+++ b/test/script/basic/JDK-8133119.js
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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-8133119: Error message associated with TypeError for call and new should include stringified Node
+ *
+ * @test
+ * @run
+ */
+
+var obj = {}
+try {
+    obj.func();
+} catch (e) {
+    print(e);
+}
+
+var arr = [33];
+try {
+    arr[0].func();
+} catch (e) {
+    print(e);
+}
+
+try {
+    new obj.func();
+} catch (e) {
+    print(e);
+}
+
+try {
+    new arr[0].func();
+} catch (e) {
+    print(e);
+}
+
+obj.foo = {}
+try {
+    new obj.foo();
+} catch (e) {
+    print(e);
+}
+
+try {
+    obj.foo();
+} catch (e) {
+    print(e);
+}
+
+var v = new java.util.Vector();
+try {
+    v();
+} catch (e) {
+    print(e);
+}
+
+try {
+    new v();
+} catch (e) {
+    print(e);
+}
diff --git a/test/script/basic/JDK-8133119.js.EXPECTED b/test/script/basic/JDK-8133119.js.EXPECTED
new file mode 100644
index 0000000..84eb39c
--- /dev/null
+++ b/test/script/basic/JDK-8133119.js.EXPECTED
@@ -0,0 +1,8 @@
+TypeError: obj.func is not a function

+TypeError: arr[0].func is not a function

+TypeError: obj.func is not a function

+TypeError: arr[0].func is not a function

+TypeError: obj.foo is not a function

+TypeError: obj.foo is not a function

+TypeError: v is not a function

+TypeError: v is not a function

diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8134488.js
similarity index 63%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8134488.js
index dfcad5a..928961a 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8134488.js
@@ -1,31 +1,46 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ * 
  * This code is free software; you can redistribute 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.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8134488: var statement in if(false) block incorrectly evacuated into enclosing function
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+var x = "string"; 
+print(x); 
+
+(function f1() { 
+    (function f2() { 
+        // If it finds both 'print' and 'x', it'll print 'string'.
+        print(x); 
+    })(); 
+
+    if (false) { 
+        (function f3() { 
+            var x; 
+        })(); 
+    } 
+
+})(); 
diff --git a/test/script/basic/JDK-8134488.js.EXPECTED b/test/script/basic/JDK-8134488.js.EXPECTED
new file mode 100644
index 0000000..b0cb3a7
--- /dev/null
+++ b/test/script/basic/JDK-8134488.js.EXPECTED
@@ -0,0 +1,2 @@
+string
+string
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8134490.js
similarity index 67%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8134490.js
index dfcad5a..d7c10fd 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8134490.js
@@ -1,31 +1,41 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ * 
  * This code is free software; you can redistribute 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.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8134490: Dead var statement evacuation incorrectly descends into nested functions
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+var v1; 
+
+function f1() 
+{ 
+v1 = 1; 
+return true; 
+(function () { var v1; })(); 
+} 
+
+f1(); 
+// If it executes without throwing an exception in code generator, it's working.
diff --git a/test/script/basic/JDK-8134569.js b/test/script/basic/JDK-8134569.js
new file mode 100644
index 0000000..7963779
--- /dev/null
+++ b/test/script/basic/JDK-8134569.js
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8134569: Add tests for prototype callsites
+ *
+ * @test
+ * @run
+ */
+
+function create() {
+    function C() {
+        this.i1 = 1;
+        this.i2 = 2;
+        this.i3 = 3;
+        return this;
+    }
+    return new C();
+}
+
+function createEmpty() {
+    function C() {
+        return this;
+    }
+    return new C();
+}
+
+function createDeep() {
+    function C() {
+        this.i1 = 1;
+        this.i2 = 2;
+        this.i3 = 3;
+        return this;
+    }
+    function D() {
+        this.p1 = 1;
+        this.p2 = 2;
+        this.p3 = 3;
+        return this;
+    }
+    C.prototype = new D();
+    return new C();
+}
+
+function createDeeper() {
+    function C() {
+        this.i1 = 1;
+        this.i2 = 2;
+        this.i3 = 3;
+        return this;
+    }
+    function D() {
+        this.p1 = 1;
+        this.p2 = 2;
+        this.p3 = 3;
+        return this;
+    }
+    function E() {
+        this.e1 = 1;
+        this.e2 = 2;
+        this.e3 = 3;
+        return this;
+    }
+    D.prototype = new E();
+    C.prototype = new D();
+    return new C();
+}
+
+function createEval() {
+    return eval("Object.create({})");
+}
+
+function p(o) { print(o.x) }
+
+function e(o) { print(o.e1) }
+
+var a, b, c;
+
+create();
+a = create();
+b = create();
+c = create();
+a.__proto__.x = 123;
+
+p(a);
+p(b);
+p(c);
+
+a = create();
+b = create();
+c = create();
+b.__proto__.x = 123;
+
+p(a);
+p(b);
+p(c);
+
+a = createEmpty();
+b = createEmpty();
+c = createEmpty();
+a.__proto__.x = 123;
+
+p(a);
+p(b);
+p(c);
+
+a = createEmpty();
+b = createEmpty();
+c = createEmpty();
+b.__proto__.x = 123;
+
+p(a);
+p(b);
+p(c);
+
+a = createDeep();
+b = createDeep();
+c = createDeep();
+a.__proto__.__proto__.x = 123;
+
+p(a);
+p(b);
+p(c);
+
+a = createDeep();
+b = createDeep();
+c = createDeep();
+b.__proto__.__proto__.x = 123;
+
+p(a);
+p(b);
+p(c);
+
+a = createDeeper();
+b = createDeeper();
+c = createDeeper();
+a.__proto__.__proto__.__proto__.x = 123;
+
+p(a);
+p(b);
+p(c);
+
+a = createDeeper();
+b = createDeeper();
+c = createDeeper();
+b.__proto__.__proto__.__proto__.x = 123;
+
+p(a);
+p(b);
+p(c);
+
+a = createDeeper();
+b = createDeeper();
+c = createDeeper();
+a.__proto__.__proto__ = null;
+
+e(a);
+e(b);
+e(c);
+
+a = createDeeper();
+b = createDeeper();
+c = createDeeper();
+b.__proto__.__proto__ = null;
+
+e(a);
+e(b);
+e(c);
+
+
+a = createEval();
+b = createEval();
+c = createEval();
+a.__proto__.x = 123;
+
+p(a);
+p(b);
+p(c);
+
+a = createEval();
+b = createEval();
+c = createEval();
+b.__proto__.x = 123;
+
+p(a);
+p(b);
+p(c);
diff --git a/test/script/basic/JDK-8134569.js.EXPECTED b/test/script/basic/JDK-8134569.js.EXPECTED
new file mode 100644
index 0000000..9793ca5
--- /dev/null
+++ b/test/script/basic/JDK-8134569.js.EXPECTED
@@ -0,0 +1,36 @@
+123
+undefined
+undefined
+undefined
+123
+undefined
+123
+undefined
+undefined
+undefined
+123
+undefined
+123
+undefined
+undefined
+undefined
+123
+undefined
+123
+undefined
+undefined
+undefined
+123
+undefined
+undefined
+1
+1
+1
+undefined
+1
+123
+undefined
+undefined
+undefined
+123
+undefined
diff --git a/test/script/basic/JDK-8134609.js b/test/script/basic/JDK-8134609.js
new file mode 100644
index 0000000..ac4c4f9
--- /dev/null
+++ b/test/script/basic/JDK-8134609.js
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8134609: Allow constructors with same prototoype map to share the allocator map
+ *
+ * @test
+ * @run
+ * @fork
+ * @option -Dnashorn.debug
+ */
+
+function createProto(members) {
+    function P() {
+        for (var id in members) {
+            if (members.hasOwnProperty(id)) {
+                this[id] = members[id];
+            }
+        }
+        return this;
+    }
+    return new P();
+}
+
+function createSubclass(prototype, members) {
+    function C() {
+        for (var id in members) {
+            if (members.hasOwnProperty(id)) {
+                this[id] = members[id];
+            }
+        }
+        return this;
+    }
+
+    C.prototype = prototype;
+
+    return new C();
+}
+
+function assertP1(object, value) {
+    Assert.assertTrue(object.p1 === value);
+}
+
+// First prototype will have non-shared proto-map. Second and third will be shared.
+var proto0 = createProto({p1: 0, p2: 1});
+var proto1 = createProto({p1: 1, p2: 2});
+var proto2 = createProto({p1: 2, p2: 3});
+
+Assert.assertTrue(Debug.map(proto1) === Debug.map(proto2));
+
+assertP1(proto1, 1);
+assertP1(proto2, 2);
+
+// First instantiation will have a non-shared prototype map, from the second one
+// maps will be shared until a different proto map comes along.
+var child0 = createSubclass(proto1, {c1: 1, c2: 2});
+var child1 = createSubclass(proto2, {c1: 2, c2: 3});
+var child2 = createSubclass(proto1, {c1: 3, c2: 4});
+var child3 = createSubclass(proto2, {c1: 1, c2: 2});
+var child4 = createSubclass(proto0, {c1: 3, c2: 2});
+
+Assert.assertTrue(Debug.map(child1) === Debug.map(child2));
+Assert.assertTrue(Debug.map(child1) === Debug.map(child3));
+Assert.assertTrue(Debug.map(child3) !== Debug.map(child4));
+
+assertP1(child1, 2);
+assertP1(child2, 1);
+assertP1(child3, 2);
+assertP1(child4, 0);
+
+Assert.assertTrue(delete proto2.p1);
+
+assertP1(child3, undefined);
+assertP1(child2, 1);
+Assert.assertTrue(Debug.map(child1) !== Debug.map(child3));
diff --git a/test/script/basic/JDK-8134731.js b/test/script/basic/JDK-8134731.js
new file mode 100644
index 0000000..e5cd339
--- /dev/null
+++ b/test/script/basic/JDK-8134731.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8134731: `Function.prototype.apply` interacts incorrectly with `arguments` 
+ *
+ * @test
+ * @run
+ */
+
+function func() {
+    return (function(f){
+        return function(a1, a2, a3, a4){
+            return (f.apply(this, arguments));
+        }
+    })(function(){
+        return arguments.length;
+    })
+}
+
+Assert.assertTrue(func()() == 0);
+Assert.assertTrue(func()(33) == 1);
+Assert.assertTrue(func()(33, true) == 2);
+Assert.assertTrue(func()(33, true, "hello") == 3);
+Assert.assertTrue(func()(33, true, "hello", "world") == 4);
+Assert.assertTrue(func()(33, true, "hello", "world", 42) == 5);
diff --git a/test/script/basic/JDK-8134939.js b/test/script/basic/JDK-8134939.js
new file mode 100644
index 0000000..67990d1
--- /dev/null
+++ b/test/script/basic/JDK-8134939.js
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8134939: Improve toString method of Dynalink OverloadedDynamicMethod
+ *
+ * @test
+ * @run
+ */
+
+var overloadedSetter = new (Java.type("jdk.nashorn.test.models.OverloadedSetter"));
+
+Assert.assertEquals(String(overloadedSetter.foo),
+  "[jdk.internal.dynalink.beans.OverloadedDynamicMethod\n" +
+  " String jdk.nashorn.test.models.OverloadedSetter.foo(String)\n" +
+  " void jdk.nashorn.test.models.OverloadedSetter.foo(int)\n" +
+  "]");
+
+Assert.assertEquals(String(overloadedSetter.setColor),
+  "[jdk.internal.dynalink.beans.OverloadedDynamicMethod\n" +
+  " void jdk.nashorn.test.models.OverloadedSetter.setColor(int)\n" +
+  " void jdk.nashorn.test.models.OverloadedSetter.setColor(String)\n" +
+  "]");
diff --git a/test/script/basic/JDK-8135000.js b/test/script/basic/JDK-8135000.js
new file mode 100644
index 0000000..34ad8e8
--- /dev/null
+++ b/test/script/basic/JDK-8135000.js
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8135000: Number.prototype.toFixed returns wrong string for 0.5 and -0.5
+ *
+ * @test
+ * @run
+ */
+
+print(-2.6.toFixed());
+print(-2.5.toFixed());
+print(-2.4.toFixed());
+print(-1.6.toFixed());
+print(-1.5.toFixed());
+print(-1.4.toFixed());
+print(-0.6.toFixed());
+print(-0.5.toFixed());
+print(-0.4.toFixed());
+print(0.4.toFixed());
+print(0.5.toFixed());
+print(0.6.toFixed());
+print(1.4.toFixed());
+print(1.5.toFixed());
+print(1.6.toFixed());
+print(2.4.toFixed());
+print(2.5.toFixed());
+print(2.6.toFixed());
diff --git a/test/script/basic/JDK-8135000.js.EXPECTED b/test/script/basic/JDK-8135000.js.EXPECTED
new file mode 100644
index 0000000..e296377
--- /dev/null
+++ b/test/script/basic/JDK-8135000.js.EXPECTED
@@ -0,0 +1,18 @@
+-3
+-3
+-2
+-2
+-2
+-1
+-1
+-1
+0
+0
+1
+1
+1
+2
+2
+2
+3
+3
diff --git a/test/script/basic/JDK-8135190.js b/test/script/basic/JDK-8135190.js
new file mode 100644
index 0000000..f6f4947
--- /dev/null
+++ b/test/script/basic/JDK-8135190.js
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8135190: Method code too large in Babel browser.js script
+ *
+ * @test
+ * @run
+ */
+
+// Make sure huge object literals are parsed correctly and don't throw
+// (using buildObject -> JSON.stringify -> eval -> testObject)
+
+function buildObject(n, d) {
+    if (n < 2) {
+        return {name: "property", type: "identifier"};
+    }
+    var obj = {};
+    for (var i = 0; i < n; i++) {
+        obj["expr" + i] = buildObject(Math.floor(n / d), d);
+    }
+    return obj;
+}
+
+function testObject(obj, n, d) {
+    var keys = Object.keys(obj);
+    if (n < 2) {
+        Assert.assertTrue(keys.length === 2);
+        Assert.assertTrue(keys[0] === "name");
+        Assert.assertTrue(keys[1] === "type");
+    } else {
+        Assert.assertTrue(keys.length === n);
+        for (var i = 0; i < n; i++) {
+            Assert.assertTrue(keys[i] === "expr" + i);
+        }
+    }
+    if (n >= 2) {
+        for (var k in keys) {
+            testObject(obj[keys[k]], Math.floor(n / d), d)
+        }
+    }
+}
+
+var fieldObject = (eval("(" + JSON.stringify(buildObject(25, 2)) + ")"));
+testObject(fieldObject, 25, 2);
+var spillObject = (eval("(" + JSON.stringify(buildObject(1000, 100)) + ")"));
+testObject(spillObject, 1000, 100);
diff --git a/test/script/basic/JDK-8136544.js b/test/script/basic/JDK-8136544.js
new file mode 100644
index 0000000..b1eeb35
--- /dev/null
+++ b/test/script/basic/JDK-8136544.js
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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-8136544: Call site switching to megamorphic causes incorrect property read
+ *
+ * @test
+ * @fork
+ * @option -Dnashorn.unstable.relink.threshold=8
+ * @run
+ */
+
+var ScriptContext = Java.type("javax.script.ScriptContext");
+var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager");
+var m = new ScriptEngineManager();
+var e = m.getEngineByName("nashorn");
+
+var scope = e.getBindings(ScriptContext.ENGINE_SCOPE);
+var MYVAR = "myvar";
+
+function loopupVar() {
+    try {
+        e.eval(MYVAR);
+        return true;
+    } catch (e) {
+        return false;
+    }
+}
+
+// make sure we exercise callsite beyond megamorphic threshold we set
+// in this test via nashorn.unstable.relink.threshold property
+// In each iteration, callsite is exercised twice (two evals)
+// So, LIMIT should be more than 4 to exercise megamorphic callsites.
+
+var LIMIT = 5; // This LIMIT should be more than 4
+
+for (var i = 0; i < LIMIT; i++) {
+    // remove the variable and lookup
+    delete scope[MYVAR];
+    Assert.assertFalse(loopupVar(), "Expected true in iteration " + i);
+
+    // set that variable and check again
+    scope[MYVAR] = "foo";
+    Assert.assertTrue(loopupVar(), "Expected false in iteration " + i);
+}
diff --git a/test/script/basic/JDK-8136694.js b/test/script/basic/JDK-8136694.js
new file mode 100644
index 0000000..29009e4
--- /dev/null
+++ b/test/script/basic/JDK-8136694.js
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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-8136694: Megemorphic scope access does not throw ReferenceError when property is missing
+ *
+ * @test
+ * @fork
+ * @option -Dnashorn.unstable.relink.threshold=16
+ * @run
+ */
+
+function checkFoo() {
+    try {
+        // The 'foo' access becomes megamorphic
+        foo;
+        return true;
+    } catch (e) {
+        return false;
+    }
+}
+
+
+// Similar check for 'with' blocks as well.
+function checkFooInWith() {
+    with({}) {
+        try {
+            // The 'foo' access becomes megamorphic
+            foo;
+            return true;
+        } catch (e) {
+            return false;
+        }
+    }
+}
+
+function loop(checker) {
+    // LIMIT has to be more than the megamorphic threashold
+    // set via @option in this test header!
+    var LIMIT = 20;
+    for (var i = 0; i < LIMIT; i++) {
+        // make sure global has no "foo"
+        delete foo;
+        Assert.assertFalse(checker(), "Expected false in interation " + i);
+
+        // now add 'foo' in global
+        foo = 44;
+        Assert.assertTrue(checker(), "Expected true in interation " + i);
+    }
+}
+
+
+loop(checkFoo);
+loop(checkFooInWith);
diff --git a/test/script/basic/JDK-8137134.js b/test/script/basic/JDK-8137134.js
new file mode 100644
index 0000000..fe4869a
--- /dev/null
+++ b/test/script/basic/JDK-8137134.js
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8137134: invokespecial on indirect super interface is generated by Java adapter generator
+ *
+ * @test
+ * @run
+ */
+
+var B = Java.type("jdk.nashorn.test.models.B");
+var b1 = new B() {}
+print(b1.a());
+print(b1.b());
+
+var b2 = new B() {
+    b: function() {
+        return "from B.b in script";
+    }
+};
+
+print(b2.a());
+print(b2.b());
+
+var b3 = new B() {
+    a: function() {
+        return "from A.a in script";
+    },
+    b: function() {
+        return "from B.b in script";
+    }
+};
+
+print(b3.a());
+print(b3.b());
diff --git a/test/script/basic/JDK-8137134.js.EXPECTED b/test/script/basic/JDK-8137134.js.EXPECTED
new file mode 100644
index 0000000..3ec4b30
--- /dev/null
+++ b/test/script/basic/JDK-8137134.js.EXPECTED
@@ -0,0 +1,6 @@
+from A.a

+from B.b

+from A.a

+from B.b in script

+from A.a in script

+from B.b in script

diff --git a/test/script/basic/JDK-8137281.js b/test/script/basic/JDK-8137281.js
new file mode 100644
index 0000000..7c12b32
--- /dev/null
+++ b/test/script/basic/JDK-8137281.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8137281: OutOfMemoryError with large numeric keys in JSON.parse
+ *
+ * @test
+ * @run
+ */
+
+function createObject(startKey, level1, level2) {
+    var root = {};
+    var key = startKey;
+    for (var i = 0; i < level1; i++) {
+        var child = {};
+        for (var j = 0; j < level2; j++) {
+            child[key++] = {};
+        }
+        root[key++] = child;
+    }
+    return root;
+}
+
+JSON.parse(JSON.stringify(createObject(500000, 20, 20)));
+JSON.parse(JSON.stringify(createObject(1000000, 20, 20)));
+JSON.parse(JSON.stringify(createObject(2000000, 20, 20)));
+JSON.parse(JSON.stringify(createObject(4000000, 20, 20)));
+JSON.parse(JSON.stringify(createObject(8000000, 20, 20)));
+JSON.parse(JSON.stringify(createObject(16000000, 20, 20)));
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8138632.js
similarity index 67%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8138632.js
index dfcad5a..cd88cda 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8138632.js
@@ -1,31 +1,35 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
+ * 
  * This code is free software; you can redistribute 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.
- *
+ * published by the Free Software Foundation.
+ * 
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * version 2 for more details (a copy is included in the LICENSE file that
  * accompanied this code).
- *
+ * 
  * You should have received a copy of the GNU General Public License version
  * 2 along with this work; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+ * 
  * Please 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;
+/**
+ * JDK-8138632: Sparse array does not handle growth of underlying dense array
+ *
+ * @test
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+var x = [];
+x[10000000] = 1;
+x[10] = 1;
+x[20] = 1;
+print(Object.keys(x));
diff --git a/test/script/basic/JDK-8138632.js.EXPECTED b/test/script/basic/JDK-8138632.js.EXPECTED
new file mode 100644
index 0000000..ef7fdec
--- /dev/null
+++ b/test/script/basic/JDK-8138632.js.EXPECTED
@@ -0,0 +1 @@
+10,20,10000000
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/JDK-8145550.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/JDK-8145550.js
index dfcad5a..90bc14c 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/JDK-8145550.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,13 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * JDK-8141537: Megamorphic invoke should use CompiledFunction variants without any LinkLogic
+ *
+ * @test
+ * @option -Dnashorn.unstable.relink.threshold=1
+ * @fork
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+load(__DIR__ + "NASHORN-421.js")
diff --git a/test/script/basic/JDK-8146147.js b/test/script/basic/JDK-8146147.js
new file mode 100644
index 0000000..7f94ea9
--- /dev/null
+++ b/test/script/basic/JDK-8146147.js
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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-8146147: Java linker indexed property getter does not work for computed nashorn string
+ *
+ * @test
+ * @run
+ */
+
+var locale = java.util.Locale.ENGLISH;
+var prop = 'ISO3Language';
+var prop1 = 'ISO3';
+var prop2 = prop1 + 'Language';
+var prop3 = String(prop2);
+
+function checkLang(obj) {
+    if (obj != "eng") {
+        throw new Error("FAILED: expected 'eng', got " + obj);
+    }
+}
+
+checkLang(locale.ISO3Language);
+checkLang(locale['ISO3Language']);
+checkLang(locale[prop]);
+checkLang(locale[prop1 + 'Language']);
+checkLang(locale[prop2]);
+checkLang(locale[prop3]);
+checkLang(locale[String(prop1 + 'Language')]);
diff --git a/test/script/basic/NASHORN-623.js.EXPECTED b/test/script/basic/NASHORN-623.js.EXPECTED
index 5755489..6b1f05b 100644
--- a/test/script/basic/NASHORN-623.js.EXPECTED
+++ b/test/script/basic/NASHORN-623.js.EXPECTED
@@ -1,3 +1,3 @@
-SyntaxError: Invalid JSON: <json>:1:12 Expected number but found ident
+SyntaxError: Invalid JSON: <json>:1:11 Invalid JSON number format
 { "test" : -xxx }
-            ^
+           ^
diff --git a/test/script/basic/NASHORN-75.js.EXPECTED b/test/script/basic/NASHORN-75.js.EXPECTED
index e1352a3..9c27c82 100644
--- a/test/script/basic/NASHORN-75.js.EXPECTED
+++ b/test/script/basic/NASHORN-75.js.EXPECTED
@@ -1,3 +1,3 @@
-TypeError: [RegExp /a|b/g] is not a function
-TypeError: [String hello] is not a function
-TypeError: [object Object] is not a function
+TypeError: RegExp("a|b", "g") is not a function

+TypeError: new String("hello") is not a function

+TypeError: new Object() is not a function

diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/apply_to_call/JDK-8145669.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/apply_to_call/JDK-8145669.js
index dfcad5a..22b6fb4 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/apply_to_call/JDK-8145669.js
@@ -1,12 +1,10 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+/* 
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,13 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/* 
+ * JDK-8145669: apply2call optimized callsite fails after becoming megamorphic
+ *
+ * @test
+ * @option -Dnashorn.unstable.relink.threshold=1
+ * @fork
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+load(__DIR__ + "apply_to_call2.js");
diff --git a/test/script/basic/apply_to_call/JDK-8145669.js.EXPECTED b/test/script/basic/apply_to_call/JDK-8145669.js.EXPECTED
new file mode 100644
index 0000000..651fbb4
--- /dev/null
+++ b/test/script/basic/apply_to_call/JDK-8145669.js.EXPECTED
@@ -0,0 +1,8 @@
+start
+4711
+23
+17
+Overwriting call now
+1
+2
+3
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/basic/apply_to_call/JDK-8145669_2.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/basic/apply_to_call/JDK-8145669_2.js
index dfcad5a..c91a9c0 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/basic/apply_to_call/JDK-8145669_2.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,13 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * JDK-8145669: apply2call optimized callsite fails after becoming megamorphic
+ *
+ * @test
+ * @option -Dnashorn.unstable.relink.threshold=1
+ * @fork
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+load(__DIR__ + "apply_to_call_varargs.js");
diff --git a/test/script/basic/apply_to_call/JDK-8145669_2.js.EXPECTED b/test/script/basic/apply_to_call/JDK-8145669_2.js.EXPECTED
new file mode 100644
index 0000000..d8f338b
--- /dev/null
+++ b/test/script/basic/apply_to_call/JDK-8145669_2.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/test/script/basic/compile-octane-splitter.js b/test/script/basic/compile-octane-splitter.js
index 58c5966..4fffaa8 100644
--- a/test/script/basic/compile-octane-splitter.js
+++ b/test/script/basic/compile-octane-splitter.js
@@ -29,11 +29,10 @@
  * forever, so make this test future safe, we specify them explicitly
  *
  * @test
- * @fork
- * @option -Dnashorn.compiler.splitter.threshold=1000
- * @fork
  * @runif external.octane
+ * @fork
  * @option -scripting
+ * @option -Dnashorn.compiler.splitter.threshold=1000
  * @option -Dnashorn.typeInfo.disabled=true
  * @option --class-cache-size=0
  * @option --persistent-code-cache=false
diff --git a/test/script/basic/errors.js.EXPECTED b/test/script/basic/errors.js.EXPECTED
index 8fae2ca..4e3385e 100644
--- a/test/script/basic/errors.js.EXPECTED
+++ b/test/script/basic/errors.js.EXPECTED
@@ -1,31 +1,31 @@
-Error is a function
-EvalError is a function
-RangeError is a function
-ReferenceError is a function
-SyntaxError is a function
-TypeError is a function
-URIError is a function
-Error.arity 1
-EvalError.arity 1
-RangeError.arity 1
-ReferenceError.arity 1
-SyntaxError.arity 1
-TypeError.arity 1
-URIError.arity 1
-true
-my error
-Error
-thrown @ 49
-true
-ReferenceError
-"foo" is not defined
-true
-TypeError
-Cannot call undefined
-Error
-EvalError
-RangeError
-ReferenceError
-SyntaxError
-TypeError
-URIError
+Error is a function

+EvalError is a function

+RangeError is a function

+ReferenceError is a function

+SyntaxError is a function

+TypeError is a function

+URIError is a function

+Error.arity 1

+EvalError.arity 1

+RangeError.arity 1

+ReferenceError.arity 1

+SyntaxError.arity 1

+TypeError.arity 1

+URIError.arity 1

+true

+my error

+Error

+thrown @ 49

+true

+ReferenceError

+"foo" is not defined

+true

+TypeError

+Object.foo_method is not a function

+Error

+EvalError

+RangeError

+ReferenceError

+SyntaxError

+TypeError

+URIError

diff --git a/test/script/basic/es6/const-reassign.js b/test/script/basic/es6/const-reassign.js
index 421d571..2d96dbf 100644
--- a/test/script/basic/es6/const-reassign.js
+++ b/test/script/basic/es6/const-reassign.js
@@ -31,144 +31,147 @@
 "use strict";
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x = 1;\n');
+    const x = 2;
+    x = 1;
+    fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x++;\n');
+    const x = 2;
+    x++;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x--;\n');
+    const x = 2;
+    x--;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        '++x;\n');
+    const x = 2;
+    ++x;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        '--x;\n');
+    const x = 2;
+    --x;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x += 1;\n');
+    const x = 2;
+    x += 1;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x *= 1;\n');
+    const x = 2;
+    x *= 1;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x /= 1;\n');
+    const x = 2;
+    x /= 1;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x %= 1;\n');
+    const x = 2;
+    x %= 1;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x |= 1;\n');
+    const x = 2;
+    x |= 1;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x &= 1;\n');
+    const x = 2;
+    x &= 1;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x ^= 1;\n');
+    const x = 2;
+    x ^= 1;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x <<= 1;\n');
+    const x = 2;
+    x <<= 1;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x >>= 1;\n');
+    const x = 2;
+    x >>= 1;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'x >>>= 1;\n');
+    const x = 2;
+    x >>>= 1;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
 
 try {
-    eval('"use strict";\n' +
-        'const x = 2;\n' +
-        'delete x;\n');
+    const x = 2;
+    delete x;
     fail("const assignment didn't throw");
 } catch (e) {
-    print(e.name);
+    print(e);
 }
+
+const c = 1;
+
+try {
+    c = 2;
+    fail("const assignment didn't throw");
+} catch (e) {
+    print(e);
+}
+
+(function() {
+    try {
+        c = 2;
+        fail("const assignment didn't throw");
+    } catch (e) {
+        print(e);
+    }
+})();
diff --git a/test/script/basic/es6/const-reassign.js.EXPECTED b/test/script/basic/es6/const-reassign.js.EXPECTED
index e1fa61a..4885f62 100644
--- a/test/script/basic/es6/const-reassign.js.EXPECTED
+++ b/test/script/basic/es6/const-reassign.js.EXPECTED
@@ -1,16 +1,18 @@
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
-SyntaxError
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+TypeError: Assignment to constant "x"
+SyntaxError: cannot delete "x" in strict mode
+TypeError: Assignment to constant "c"
+TypeError: Assignment to constant "c"
diff --git a/test/script/basic/es6/let-eval.js b/test/script/basic/es6/let-eval.js
index b08fa98..d1855dc 100644
--- a/test/script/basic/es6/let-eval.js
+++ b/test/script/basic/es6/let-eval.js
@@ -96,3 +96,9 @@
 f();
 
 print(typeof a, typeof b, typeof c, typeof x, typeof z);
+
+let v = 1;
+eval("print('v: ' + v); v = 2; print ('v: ' + v);");
+print("this.v: " + this.v);
+print("v: " + v);
+
diff --git a/test/script/basic/es6/let-eval.js.EXPECTED b/test/script/basic/es6/let-eval.js.EXPECTED
index 96f9a6d..d6ccc59 100644
--- a/test/script/basic/es6/let-eval.js.EXPECTED
+++ b/test/script/basic/es6/let-eval.js.EXPECTED
@@ -14,3 +14,7 @@
 2 1 0
 2 1 0 undefined
 undefined undefined undefined undefined undefined
+v: 1
+v: 2
+this.v: undefined
+v: 2
diff --git a/test/script/basic/es6/let_const_reuse.js.EXPECTED b/test/script/basic/es6/let_const_reuse.js.EXPECTED
index fa875c7..1690870 100644
--- a/test/script/basic/es6/let_const_reuse.js.EXPECTED
+++ b/test/script/basic/es6/let_const_reuse.js.EXPECTED
@@ -1,8 +1,4 @@
 ReferenceError: "a" is not defined
-SyntaxError: test/script/basic/es6/let_const_reuse.js#35:9<eval>:3:8 Assignment to constant "a"
-        a--
-        ^
-SyntaxError: test/script/basic/es6/let_const_reuse.js#35:9<eval>:3:8 Assignment to constant "a"
-        a--
-        ^
+TypeError: Assignment to constant "a"
+TypeError: Assignment to constant "a"
 ReferenceError: "a" is not defined
diff --git a/test/script/basic/javaarrayconversion.js b/test/script/basic/javaarrayconversion.js
index 6168247..37bf468 100644
--- a/test/script/basic/javaarrayconversion.js
+++ b/test/script/basic/javaarrayconversion.js
@@ -128,24 +128,32 @@
 // Converting to string, toString takes precedence over valueOf
 test({ valueOf: function() { return "42"; },  toString: function() { return "43"; } }, "java.lang.String", "43")
 
+function assertCanConvert(sourceType, targetType) {
+  Java.to([new (Java.type(sourceType))()], targetType + "[]")
+  ++testCount;
+}
+
 function assertCantConvert(sourceType, targetType) {
   try {
-    Java.to([new Java.type(sourceType)()], targetType + "[]")
+    Java.to([new (Java.type(sourceType))()], targetType + "[]")
     throw "no TypeError encountered"
   } catch(e) {
-      if(!(e instanceof TypeError)) {
+      if(!(e instanceof TypeError) ||
+          !e.message.startsWith("Java.to conversion to array type")) {
         throw e;
       }
       ++testCount;
   }
 }
 
+// Arbitrary POJOs to JS Primitive type should work
+assertCanConvert("java.util.BitSet", "int")
+assertCanConvert("java.util.BitSet", "double")
+assertCanConvert("java.util.BitSet", "long")
+assertCanConvert("java.util.BitSet", "boolean")
+assertCanConvert("java.util.BitSet", "java.lang.String")
+
 // Arbitrary POJOs can't be converted to Java values
-assertCantConvert("java.util.BitSet", "int")
-assertCantConvert("java.util.BitSet", "double")
-assertCantConvert("java.util.BitSet", "long")
-assertCantConvert("java.util.BitSet", "boolean")
-assertCantConvert("java.util.BitSet", "java.lang.String")
 assertCantConvert("java.util.BitSet", "java.lang.Double")
 assertCantConvert("java.util.BitSet", "java.lang.Long")
 
diff --git a/test/script/basic/typedarrays.js b/test/script/basic/typedarrays.js
index b15f5dd..d66c79b 100644
--- a/test/script/basic/typedarrays.js
+++ b/test/script/basic/typedarrays.js
@@ -28,6 +28,17 @@
  * @run
  */
 
+//JDK-8066217, constructor for arraybuffer not behaving as per spec
+function checkLength(ab, l) {
+    if (ab.byteLength != l) {
+        throw "length error: " + ab.byteLength + " != " + l;
+    }
+}
+checkLength(new ArrayBuffer(), 0);
+checkLength(new ArrayBuffer(0), 0);
+checkLength(new ArrayBuffer(1024), 1024);
+checkLength(new ArrayBuffer(1,2,3), 1);
+checkLength(new ArrayBuffer([17]), 17);
 
 var typeDefinitions = [
 Int8Array,
diff --git a/test/script/currently-failing/gettersetter.js b/test/script/currently-failing/gettersetter.js
index 5fec25d..b484c92 100644
--- a/test/script/currently-failing/gettersetter.js
+++ b/test/script/currently-failing/gettersetter.js
@@ -1,5 +1,5 @@
 /*
- * 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
diff --git a/test/script/currently-failing/property_delete.js b/test/script/currently-failing/property_delete.js
index ab508bf..c027058 100644
--- a/test/script/currently-failing/property_delete.js
+++ b/test/script/currently-failing/property_delete.js
@@ -1,5 +1,5 @@
 /*
- * 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
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/error/JDK-8098847.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/error/JDK-8098847.js
index dfcad5a..f7d686c 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/error/JDK-8098847.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,13 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * JDK-8098847: obj."prop" and obj.'prop' should result in SyntaxError
+ *
+ * @test/compile-error
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+var obj = { "prop": 45 };
+
+obj."prop" = "hello";
+obj.'prop' = "hello";
diff --git a/test/script/error/JDK-8098847.js.EXPECTED b/test/script/error/JDK-8098847.js.EXPECTED
new file mode 100644
index 0000000..97611ac
--- /dev/null
+++ b/test/script/error/JDK-8098847.js.EXPECTED
@@ -0,0 +1,6 @@
+test/script/error/JDK-8098847.js:32:5 Expected ident but found prop
+obj."prop" = "hello";
+     ^
+test/script/error/JDK-8098847.js:33:5 Expected ident but found prop
+obj.'prop' = "hello";
+     ^
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/error/anon_func_stat_nse.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/error/anon_func_stat_nse.js
index dfcad5a..abe1518 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/error/anon_func_stat_nse.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,11 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * Anonymous function statement should result in error in -nse
+ *
+ * @option -nse
+ * @test/compile-error
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+function() {}
diff --git a/test/script/error/anon_func_stat_nse.js.EXPECTED b/test/script/error/anon_func_stat_nse.js.EXPECTED
new file mode 100644
index 0000000..350f71c
--- /dev/null
+++ b/test/script/error/anon_func_stat_nse.js.EXPECTED
@@ -0,0 +1,3 @@
+test/script/error/anon_func_stat_nse.js:31:8 Expected ident but found (
+function() {}
+        ^
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/error/backquote_string_nse.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/error/backquote_string_nse.js
index dfcad5a..25dbbb1 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/error/backquote_string_nse.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,12 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * Backquote string should result in error with -nse even with -scripting
+ *
+ * @option -nse
+ * @option -scripting
+ * @test/compile-error
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+`ls -l`;
diff --git a/test/script/error/backquote_string_nse.js.EXPECTED b/test/script/error/backquote_string_nse.js.EXPECTED
new file mode 100644
index 0000000..dd1eac2
--- /dev/null
+++ b/test/script/error/backquote_string_nse.js.EXPECTED
@@ -0,0 +1,3 @@
+test/script/error/backquote_string_nse.js:32:0 Expected an operand but found error
+`ls -l`;
+^
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/error/conditional_catch_nse.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/error/conditional_catch_nse.js
index dfcad5a..ac1db20 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/error/conditional_catch_nse.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,14 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * conditional catch should result in error with -nse
+ *
+ * @option -nse
+ * @test/compile-error
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
+try {
+    func();
+} catch (e if e instanceof ReferenceError) {
 }
diff --git a/test/script/error/conditional_catch_nse.js.EXPECTED b/test/script/error/conditional_catch_nse.js.EXPECTED
new file mode 100644
index 0000000..2f8ed28
--- /dev/null
+++ b/test/script/error/conditional_catch_nse.js.EXPECTED
@@ -0,0 +1,6 @@
+test/script/error/conditional_catch_nse.js:33:11 Expected ) but found if
+} catch (e if e instanceof ReferenceError) {
+           ^
+test/script/error/conditional_catch_nse.js:34:0 Expected eof but found }
+}
+^
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/error/expr_closure_nse.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/error/expr_closure_nse.js
index dfcad5a..16a3085 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/error/expr_closure_nse.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,11 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * Expression closures should result in error with -nse
+ *
+ * @option -nse
+ * @test/compile-error
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+function square(x) x*x;
diff --git a/test/script/error/expr_closure_nse.js.EXPECTED b/test/script/error/expr_closure_nse.js.EXPECTED
new file mode 100644
index 0000000..da99c70
--- /dev/null
+++ b/test/script/error/expr_closure_nse.js.EXPECTED
@@ -0,0 +1,3 @@
+test/script/error/expr_closure_nse.js:31:19 Expected { but found x
+function square(x) x*x;
+                   ^
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/error/for_each_nse.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/error/for_each_nse.js
index dfcad5a..b26b5ca 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/error/for_each_nse.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,13 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * for..each should result in error with -nse
+ *
+ * @option -nse
+ * @test/compile-error
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
+for each (var x in [3, 454, 4]) {
+    print(x);
 }
diff --git a/test/script/error/for_each_nse.js.EXPECTED b/test/script/error/for_each_nse.js.EXPECTED
new file mode 100644
index 0000000..51dd2ff
--- /dev/null
+++ b/test/script/error/for_each_nse.js.EXPECTED
@@ -0,0 +1,6 @@
+test/script/error/for_each_nse.js:31:4 Expected ( but found each
+for each (var x in [3, 454, 4]) {
+    ^
+test/script/error/for_each_nse.js:33:0 Expected eof but found }
+}
+^
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/error/hash_comment_nse.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/error/hash_comment_nse.js
index dfcad5a..3f27e5d 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/error/hash_comment_nse.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,12 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * Hash comment should result in error with -nse even with -scripting
+ *
+ * @option -nse
+ * @option -scripting
+ * @test/compile-error
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+# this is a comment
diff --git a/test/script/error/hash_comment_nse.js.EXPECTED b/test/script/error/hash_comment_nse.js.EXPECTED
new file mode 100644
index 0000000..1d1cafe
--- /dev/null
+++ b/test/script/error/hash_comment_nse.js.EXPECTED
@@ -0,0 +1,3 @@
+test/script/error/hash_comment_nse.js:32:0 Expected an operand but found error
+# this is a comment
+^
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/error/heredoc_nse.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/error/heredoc_nse.js
index dfcad5a..925f2ae 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/error/heredoc_nse.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,15 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * Heredoc string should result in error with -nse even with -scripting
+ *
+ * @option -nse
+ * @option -scripting
+ * @test/compile-error
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+var str = <<EOF
+This is a multiple line string
+inside a heredoc
+EOF;
diff --git a/test/script/error/heredoc_nse.js.EXPECTED b/test/script/error/heredoc_nse.js.EXPECTED
new file mode 100644
index 0000000..e0b3cc2
--- /dev/null
+++ b/test/script/error/heredoc_nse.js.EXPECTED
@@ -0,0 +1,9 @@
+test/script/error/heredoc_nse.js:32:10 Expected an operand but found <<
+var str = <<EOF
+          ^
+test/script/error/heredoc_nse.js:33:5 Expected ; but found is
+This is a multiple line string
+     ^
+test/script/error/heredoc_nse.js:34:7 Expected ; but found a
+inside a heredoc
+       ^
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/error/object_literal_in_new_nse.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/error/object_literal_in_new_nse.js
index dfcad5a..8200132 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/error/object_literal_in_new_nse.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,13 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * Object literal outside 'new' should result in error in -nse
+ *
+ * @option -nse
+ * @test/compile-error
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
+var r = new java.lang.Runnable() {
+  run: function() { print("hello"); }
 }
diff --git a/test/script/error/object_literal_in_new_nse.js.EXPECTED b/test/script/error/object_literal_in_new_nse.js.EXPECTED
new file mode 100644
index 0000000..f925d74
--- /dev/null
+++ b/test/script/error/object_literal_in_new_nse.js.EXPECTED
@@ -0,0 +1,9 @@
+test/script/error/object_literal_in_new_nse.js:31:33 Expected ; but found {
+var r = new java.lang.Runnable() {
+                                 ^
+test/script/error/object_literal_in_new_nse.js:32:15 Expected ident but found (
+  run: function() { print("hello"); }
+               ^
+test/script/error/object_literal_in_new_nse.js:32:36 Expected eof but found }
+  run: function() { print("hello"); }
+                                    ^
diff --git a/test/script/maptests/builtins.js b/test/script/maptests/builtins.js
index 8bfd848..ce7f90b 100644
--- a/test/script/maptests/builtins.js
+++ b/test/script/maptests/builtins.js
@@ -1,5 +1,5 @@
 /*
- * 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
diff --git a/test/script/maptests/constructor.js b/test/script/maptests/constructor.js
index f409ce1..92fc481 100644
--- a/test/script/maptests/constructor.js
+++ b/test/script/maptests/constructor.js
@@ -1,5 +1,5 @@
 /*
- * 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
diff --git a/test/script/maptests/maputil.js b/test/script/maptests/maputil.js
index 2294e75..a4a95bd 100644
--- a/test/script/maptests/maputil.js
+++ b/test/script/maptests/maputil.js
@@ -1,5 +1,5 @@
 /*
- * 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
diff --git a/test/script/maptests/object_create.js b/test/script/maptests/object_create.js
index e0b5f60..8d94fd5 100644
--- a/test/script/maptests/object_create.js
+++ b/test/script/maptests/object_create.js
@@ -1,5 +1,5 @@
 /*
- * 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
diff --git a/test/script/maptests/object_literals.js b/test/script/maptests/object_literals.js
index b379ac6..6d3f656 100644
--- a/test/script/maptests/object_literals.js
+++ b/test/script/maptests/object_literals.js
@@ -1,5 +1,5 @@
 /*
- * 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
diff --git a/test/script/maptests/point.js b/test/script/maptests/point.js
index 06b64dd..78b33fa 100644
--- a/test/script/maptests/point.js
+++ b/test/script/maptests/point.js
@@ -1,5 +1,5 @@
 /*
- * 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
diff --git a/test/script/maptests/property_add.js b/test/script/maptests/property_add.js
index 606f2d0..31637dc 100644
--- a/test/script/maptests/property_add.js
+++ b/test/script/maptests/property_add.js
@@ -1,5 +1,5 @@
 /*
- * 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
diff --git a/test/script/maptests/proto.js b/test/script/maptests/proto.js
index 5bc3332..167397a 100644
--- a/test/script/maptests/proto.js
+++ b/test/script/maptests/proto.js
@@ -1,5 +1,5 @@
 /*
- * 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
diff --git a/test/script/nosecurity/JDK-8050964.js b/test/script/nosecurity/JDK-8050964.js
index eda3d1b..59d9c8d 100644
--- a/test/script/nosecurity/JDK-8050964.js
+++ b/test/script/nosecurity/JDK-8050964.js
@@ -47,7 +47,7 @@
 }
 
 var javahome = System.getProperty("java.home");
-var jdepsPath = javahome + "/../bin/jdeps".replaceAll(/\//g, File.separater);
+var jdepsPath = javahome + "/../bin/jdeps".replace(/\//g, File.separator);
 
 // run jdep on nashorn.jar - only summary but print profile info
 $ENV.PWD=System.getProperty("user.dir") // to avoid RE on Cygwin
diff --git a/test/script/nosecurity/JDK-8055034.js b/test/script/nosecurity/JDK-8055034.js
index a0e5057..9c04569 100644
--- a/test/script/nosecurity/JDK-8055034.js
+++ b/test/script/nosecurity/JDK-8055034.js
@@ -48,7 +48,7 @@
 // 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);
+jjsCmd = jjsCmd.toString().replace(/\//g, File.separator);
 $ENV.PWD=System.getProperty("user.dir") // to avoid RE on Cygwin
 $EXEC(jjsCmd, "var x = Object.create(null);\nx;\nprint('PASSED');\nexit(0)");
 
diff --git a/test/script/nosecurity/JDK-8067215.js b/test/script/nosecurity/JDK-8067215.js
new file mode 100644
index 0000000..12877ac
--- /dev/null
+++ b/test/script/nosecurity/JDK-8067215.js
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8067215: Disable dual fields when not using optimistic types
+ *
+ * @test
+ * @run
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+var intType    = Java.type("int");
+var doubleType = Java.type("double");
+var longType   = Java.type("long");
+var objectType = Java.type("java.lang.Object");
+
+var Context = Java.type("jdk.nashorn.internal.runtime.Context");
+var JSType  = Java.type("jdk.nashorn.internal.runtime.JSType");
+
+var context = Context.getContext();
+var dualFields = context.useDualFields();
+var optimisticTypes = context.getEnv()._optimistic_types;
+
+if (dualFields != optimisticTypes) {
+    throw new Error("Wrong dual fields setting");
+}
+
+function testMap(obj) {
+    obj.x = "foo";
+    obj["y"] = 0;
+    Object.defineProperty(obj, "z", {value: 0.5});
+    var map = Debug.map(obj);
+    for (var key in obj) {
+        var prop = map.findProperty(key);
+        if (prop.hasDualFields() !== dualFields) {
+            throw new Error("Wrong property flags: " + prop);
+        }
+        if (prop.getType() != getExpectedType(obj[key])) {
+            throw new Error("Wrong property type: " + prop.getType() + " // " + getExpectedType(obj[key]));
+
+        }
+    }
+}
+
+function getExpectedType(value) {
+    if (!dualFields) {
+        return objectType.class;
+    }
+    if (JSType.isRepresentableAsInt(value)) {
+        return intType.class;
+    }
+    if (JSType.isRepresentableAsLong(value)) {
+        return longType.class;
+    }
+    if (JSType.isNumber(value)) {
+        return doubleType.class;
+    }
+    return objectType.class;
+}
+
+var o = {
+    a: 1,
+    b: 2.5,
+    c: 0x10000000000,
+    d: true
+};
+
+function C() {
+    this.a = 1;
+    this.b = 2.5;
+    this.c = 0x10000000000;
+    this.d = true;
+}
+
+var a = 1;
+var b = 2.5;
+var c = 0x10000000000;
+var d = true;
+
+testMap(o);
+testMap(new C());
+testMap(JSON.parse('{ "a": 1, "b": 2.5, "c": 1099511627776, "d": true }'));
+testMap(this);
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/nosecurity/JDK-8073613.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/nosecurity/JDK-8073613.js
index dfcad5a..5376ba7 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/nosecurity/JDK-8073613.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,30 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * JDK-8073613: Here documents: how to avoid string interpolation?
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
-}
+var a = 2,
+    b = 3
+
+print(<<EOD)
+${a}${b}
+EOD
+
+print(<<"EOD")
+${a}${b}
+EOD
+
+print(<<'EOM')
+${a}${b}
+EOM
+
+print(<<"EOM")
+$\{a}
+EOM
+
diff --git a/test/script/nosecurity/JDK-8073613.js.EXPECTED b/test/script/nosecurity/JDK-8073613.js.EXPECTED
new file mode 100644
index 0000000..7ef62b4
--- /dev/null
+++ b/test/script/nosecurity/JDK-8073613.js.EXPECTED
@@ -0,0 +1,4 @@
+23
+${a}${b}
+${a}${b}
+$\{a}
diff --git a/test/script/nosecurity/JDK-8078049.js b/test/script/nosecurity/JDK-8078049.js
new file mode 100644
index 0000000..6a441a1
--- /dev/null
+++ b/test/script/nosecurity/JDK-8078049.js
@@ -0,0 +1,553 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please 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-8078049: Nashorn crashes when attempting to start the new tsc.js compiler for TypeScript
+ *
+ * @test
+ * @run
+ * @fork
+ * @option -Dnashorn.debug=true
+ */
+
+var m = 1;
+
+var fields = {
+    p0: { code: 0, category: m },
+    p1: { code: 1, category: m },
+    p2: { code: 2, category: m }
+};
+
+var spill = {
+    p0: { code: 0, category: m },
+    p1: { code: 1, category: m },
+    p2: { code: 2, category: m },
+    p3: { code: 3, category: m },
+    p4: { code: 4, category: m },
+    p5: { code: 5, category: m },
+    p6: { code: 6, category: m },
+    p7: { code: 7, category: m },
+    p8: { code: 8, category: m },
+    p9: { code: 9, category: m },
+    p10: { code: 10, category: m },
+    p11: { code: 11, category: m },
+    p12: { code: 12, category: m },
+    p13: { code: 13, category: m },
+    p14: { code: 14, category: m },
+    p15: { code: 15, category: m },
+    p16: { code: 16, category: m },
+    p17: { code: 17, category: m },
+    p18: { code: 18, category: m },
+    p19: { code: 19, category: m },
+    p20: { code: 20, category: m },
+    p21: { code: 21, category: m },
+    p22: { code: 22, category: m },
+    p23: { code: 23, category: m },
+    p24: { code: 24, category: m },
+    p25: { code: 25, category: m },
+    p26: { code: 26, category: m },
+    p27: { code: 27, category: m },
+    p28: { code: 28, category: m },
+    p29: { code: 29, category: m },
+    p30: { code: 30, category: m },
+    p31: { code: 31, category: m },
+    p32: { code: 32, category: m },
+    p33: { code: 33, category: m },
+    p34: { code: 34, category: m },
+    p35: { code: 35, category: m },
+    p36: { code: 36, category: m },
+    p37: { code: 37, category: m },
+    p38: { code: 38, category: m },
+    p39: { code: 39, category: m },
+    p40: { code: 40, category: m },
+    p41: { code: 41, category: m },
+    p42: { code: 42, category: m },
+    p43: { code: 43, category: m },
+    p44: { code: 44, category: m },
+    p45: { code: 45, category: m },
+    p46: { code: 46, category: m },
+    p47: { code: 47, category: m },
+    p48: { code: 48, category: m },
+    p49: { code: 49, category: m },
+    p50: { code: 50, category: m },
+    p51: { code: 51, category: m },
+    p52: { code: 52, category: m },
+    p53: { code: 53, category: m },
+    p54: { code: 54, category: m },
+    p55: { code: 55, category: m },
+    p56: { code: 56, category: m },
+    p57: { code: 57, category: m },
+    p58: { code: 58, category: m },
+    p59: { code: 59, category: m },
+    p60: { code: 60, category: m },
+    p61: { code: 61, category: m },
+    p62: { code: 62, category: m },
+    p63: { code: 63, category: m },
+    p64: { code: 64, category: m },
+    p65: { code: 65, category: m },
+    p66: { code: 66, category: m },
+    p67: { code: 67, category: m },
+    p68: { code: 68, category: m },
+    p69: { code: 69, category: m },
+    p70: { code: 70, category: m },
+    p71: { code: 71, category: m },
+    p72: { code: 72, category: m },
+    p73: { code: 73, category: m },
+    p74: { code: 74, category: m },
+    p75: { code: 75, category: m },
+    p76: { code: 76, category: m },
+    p77: { code: 77, category: m },
+    p78: { code: 78, category: m },
+    p79: { code: 79, category: m },
+    p80: { code: 80, category: m },
+    p81: { code: 81, category: m },
+    p82: { code: 82, category: m },
+    p83: { code: 83, category: m },
+    p84: { code: 84, category: m },
+    p85: { code: 85, category: m },
+    p86: { code: 86, category: m },
+    p87: { code: 87, category: m },
+    p88: { code: 88, category: m },
+    p89: { code: 89, category: m },
+    p90: { code: 90, category: m },
+    p91: { code: 91, category: m },
+    p92: { code: 92, category: m },
+    p93: { code: 93, category: m },
+    p94: { code: 94, category: m },
+    p95: { code: 95, category: m },
+    p96: { code: 96, category: m },
+    p97: { code: 97, category: m },
+    p98: { code: 98, category: m },
+    p99: { code: 99, category: m },
+    p100: { code: 100, category: m },
+    p101: { code: 101, category: m },
+    p102: { code: 102, category: m },
+    p103: { code: 103, category: m },
+    p104: { code: 104, category: m },
+    p105: { code: 105, category: m },
+    p106: { code: 106, category: m },
+    p107: { code: 107, category: m },
+    p108: { code: 108, category: m },
+    p109: { code: 109, category: m },
+    p110: { code: 110, category: m },
+    p111: { code: 111, category: m },
+    p112: { code: 112, category: m },
+    p113: { code: 113, category: m },
+    p114: { code: 114, category: m },
+    p115: { code: 115, category: m },
+    p116: { code: 116, category: m },
+    p117: { code: 117, category: m },
+    p118: { code: 118, category: m },
+    p119: { code: 119, category: m },
+    p120: { code: 120, category: m },
+    p121: { code: 121, category: m },
+    p122: { code: 122, category: m },
+    p123: { code: 123, category: m },
+    p124: { code: 124, category: m },
+    p125: { code: 125, category: m },
+    p126: { code: 126, category: m },
+    p127: { code: 127, category: m },
+    p128: { code: 128, category: m },
+    p129: { code: 129, category: m },
+    p130: { code: 130, category: m },
+    p131: { code: 131, category: m },
+    p132: { code: 132, category: m },
+    p133: { code: 133, category: m },
+    p134: { code: 134, category: m },
+    p135: { code: 135, category: m },
+    p136: { code: 136, category: m },
+    p137: { code: 137, category: m },
+    p138: { code: 138, category: m },
+    p139: { code: 139, category: m },
+    p140: { code: 140, category: m },
+    p141: { code: 141, category: m },
+    p142: { code: 142, category: m },
+    p143: { code: 143, category: m },
+    p144: { code: 144, category: m },
+    p145: { code: 145, category: m },
+    p146: { code: 146, category: m },
+    p147: { code: 147, category: m },
+    p148: { code: 148, category: m },
+    p149: { code: 149, category: m },
+    p150: { code: 150, category: m },
+    p151: { code: 151, category: m },
+    p152: { code: 152, category: m },
+    p153: { code: 153, category: m },
+    p154: { code: 154, category: m },
+    p155: { code: 155, category: m },
+    p156: { code: 156, category: m },
+    p157: { code: 157, category: m },
+    p158: { code: 158, category: m },
+    p159: { code: 159, category: m },
+    p160: { code: 160, category: m },
+    p161: { code: 161, category: m },
+    p162: { code: 162, category: m },
+    p163: { code: 163, category: m },
+    p164: { code: 164, category: m },
+    p165: { code: 165, category: m },
+    p166: { code: 166, category: m },
+    p167: { code: 167, category: m },
+    p168: { code: 168, category: m },
+    p169: { code: 169, category: m },
+    p170: { code: 170, category: m },
+    p171: { code: 171, category: m },
+    p172: { code: 172, category: m },
+    p173: { code: 173, category: m },
+    p174: { code: 174, category: m },
+    p175: { code: 175, category: m },
+    p176: { code: 176, category: m },
+    p177: { code: 177, category: m },
+    p178: { code: 178, category: m },
+    p179: { code: 179, category: m },
+    p180: { code: 180, category: m },
+    p181: { code: 181, category: m },
+    p182: { code: 182, category: m },
+    p183: { code: 183, category: m },
+    p184: { code: 184, category: m },
+    p185: { code: 185, category: m },
+    p186: { code: 186, category: m },
+    p187: { code: 187, category: m },
+    p188: { code: 188, category: m },
+    p189: { code: 189, category: m },
+    p190: { code: 190, category: m },
+    p191: { code: 191, category: m },
+    p192: { code: 192, category: m },
+    p193: { code: 193, category: m },
+    p194: { code: 194, category: m },
+    p195: { code: 195, category: m },
+    p196: { code: 196, category: m },
+    p197: { code: 197, category: m },
+    p198: { code: 198, category: m },
+    p199: { code: 199, category: m },
+    p200: { code: 200, category: m },
+    p201: { code: 201, category: m },
+    p202: { code: 202, category: m },
+    p203: { code: 203, category: m },
+    p204: { code: 204, category: m },
+    p205: { code: 205, category: m },
+    p206: { code: 206, category: m },
+    p207: { code: 207, category: m },
+    p208: { code: 208, category: m },
+    p209: { code: 209, category: m },
+    p210: { code: 210, category: m },
+    p211: { code: 211, category: m },
+    p212: { code: 212, category: m },
+    p213: { code: 213, category: m },
+    p214: { code: 214, category: m },
+    p215: { code: 215, category: m },
+    p216: { code: 216, category: m },
+    p217: { code: 217, category: m },
+    p218: { code: 218, category: m },
+    p219: { code: 219, category: m },
+    p220: { code: 220, category: m },
+    p221: { code: 221, category: m },
+    p222: { code: 222, category: m },
+    p223: { code: 223, category: m },
+    p224: { code: 224, category: m },
+    p225: { code: 225, category: m },
+    p226: { code: 226, category: m },
+    p227: { code: 227, category: m },
+    p228: { code: 228, category: m },
+    p229: { code: 229, category: m },
+    p230: { code: 230, category: m },
+    p231: { code: 231, category: m },
+    p232: { code: 232, category: m },
+    p233: { code: 233, category: m },
+    p234: { code: 234, category: m },
+    p235: { code: 235, category: m },
+    p236: { code: 236, category: m },
+    p237: { code: 237, category: m },
+    p238: { code: 238, category: m },
+    p239: { code: 239, category: m },
+    p240: { code: 240, category: m },
+    p241: { code: 241, category: m },
+    p242: { code: 242, category: m },
+    p243: { code: 243, category: m },
+    p244: { code: 244, category: m },
+    p245: { code: 245, category: m },
+    p246: { code: 246, category: m },
+    p247: { code: 247, category: m },
+    p248: { code: 248, category: m },
+    p249: { code: 249, category: m },
+    p250: { code: 250, category: m },
+    p251: { code: 251, category: m },
+    p252: { code: 252, category: m },
+    p253: { code: 253, category: m },
+    p254: { code: 254, category: m },
+    p255: { code: 255, category: m },
+    p256: { code: 256, category: m },
+    p257: { code: 257, category: m },
+    p258: { code: 258, category: m },
+    p259: { code: 259, category: m },
+    p260: { code: 260, category: m },
+    p261: { code: 261, category: m },
+    p262: { code: 262, category: m },
+    p263: { code: 263, category: m },
+    p264: { code: 264, category: m },
+    p265: { code: 265, category: m },
+    p266: { code: 266, category: m },
+    p267: { code: 267, category: m },
+    p268: { code: 268, category: m },
+    p269: { code: 269, category: m },
+    p270: { code: 270, category: m },
+    p271: { code: 271, category: m },
+    p272: { code: 272, category: m },
+    p273: { code: 273, category: m },
+    p274: { code: 274, category: m },
+    p275: { code: 275, category: m },
+    p276: { code: 276, category: m },
+    p277: { code: 277, category: m },
+    p278: { code: 278, category: m },
+    p279: { code: 279, category: m },
+    p280: { code: 280, category: m },
+    p281: { code: 281, category: m },
+    p282: { code: 282, category: m },
+    p283: { code: 283, category: m },
+    p284: { code: 284, category: m },
+    p285: { code: 285, category: m },
+    p286: { code: 286, category: m },
+    p287: { code: 287, category: m },
+    p288: { code: 288, category: m },
+    p289: { code: 289, category: m },
+    p290: { code: 290, category: m },
+    p291: { code: 291, category: m },
+    p292: { code: 292, category: m },
+    p293: { code: 293, category: m },
+    p294: { code: 294, category: m },
+    p295: { code: 295, category: m },
+    p296: { code: 296, category: m },
+    p297: { code: 297, category: m },
+    p298: { code: 298, category: m },
+    p299: { code: 299, category: m },
+    p300: { code: 300, category: m },
+    p301: { code: 301, category: m },
+    p302: { code: 302, category: m },
+    p303: { code: 303, category: m },
+    p304: { code: 304, category: m },
+    p305: { code: 305, category: m },
+    p306: { code: 306, category: m },
+    p307: { code: 307, category: m },
+    p308: { code: 308, category: m },
+    p309: { code: 309, category: m },
+    p310: { code: 310, category: m },
+    p311: { code: 311, category: m },
+    p312: { code: 312, category: m },
+    p313: { code: 313, category: m },
+    p314: { code: 314, category: m },
+    p315: { code: 315, category: m },
+    p316: { code: 316, category: m },
+    p317: { code: 317, category: m },
+    p318: { code: 318, category: m },
+    p319: { code: 319, category: m },
+    p320: { code: 320, category: m },
+    p321: { code: 321, category: m },
+    p322: { code: 322, category: m },
+    p323: { code: 323, category: m },
+    p324: { code: 324, category: m },
+    p325: { code: 325, category: m },
+    p326: { code: 326, category: m },
+    p327: { code: 327, category: m },
+    p328: { code: 328, category: m },
+    p329: { code: 329, category: m },
+    p330: { code: 330, category: m },
+    p331: { code: 331, category: m },
+    p332: { code: 332, category: m },
+    p333: { code: 333, category: m },
+    p334: { code: 334, category: m },
+    p335: { code: 335, category: m },
+    p336: { code: 336, category: m },
+    p337: { code: 337, category: m },
+    p338: { code: 338, category: m },
+    p339: { code: 339, category: m },
+    p340: { code: 340, category: m },
+    p341: { code: 341, category: m },
+    p342: { code: 342, category: m },
+    p343: { code: 343, category: m },
+    p344: { code: 344, category: m },
+    p345: { code: 345, category: m },
+    p346: { code: 346, category: m },
+    p347: { code: 347, category: m },
+    p348: { code: 348, category: m },
+    p349: { code: 349, category: m },
+    p350: { code: 350, category: m },
+    p351: { code: 351, category: m },
+    p352: { code: 352, category: m },
+    p353: { code: 353, category: m },
+    p354: { code: 354, category: m },
+    p355: { code: 355, category: m },
+    p356: { code: 356, category: m },
+    p357: { code: 357, category: m },
+    p358: { code: 358, category: m },
+    p359: { code: 359, category: m },
+    p360: { code: 360, category: m },
+    p361: { code: 361, category: m },
+    p362: { code: 362, category: m },
+    p363: { code: 363, category: m },
+    p364: { code: 364, category: m },
+    p365: { code: 365, category: m },
+    p366: { code: 366, category: m },
+    p367: { code: 367, category: m },
+    p368: { code: 368, category: m },
+    p369: { code: 369, category: m },
+    p370: { code: 370, category: m },
+    p371: { code: 371, category: m },
+    p372: { code: 372, category: m },
+    p373: { code: 373, category: m },
+    p374: { code: 374, category: m },
+    p375: { code: 375, category: m },
+    p376: { code: 376, category: m },
+    p377: { code: 377, category: m },
+    p378: { code: 378, category: m },
+    p379: { code: 379, category: m },
+    p380: { code: 380, category: m },
+    p381: { code: 381, category: m },
+    p382: { code: 382, category: m },
+    p383: { code: 383, category: m },
+    p384: { code: 384, category: m },
+    p385: { code: 385, category: m },
+    p386: { code: 386, category: m },
+    p387: { code: 387, category: m },
+    p388: { code: 388, category: m },
+    p389: { code: 389, category: m },
+    p390: { code: 390, category: m },
+    p391: { code: 391, category: m },
+    p392: { code: 392, category: m },
+    p393: { code: 393, category: m },
+    p394: { code: 394, category: m },
+    p395: { code: 395, category: m },
+    p396: { code: 396, category: m },
+    p397: { code: 397, category: m },
+    p398: { code: 398, category: m },
+    p399: { code: 399, category: m },
+    p400: { code: 400, category: m },
+    p401: { code: 401, category: m },
+    p402: { code: 402, category: m },
+    p403: { code: 403, category: m },
+    p404: { code: 404, category: m },
+    p405: { code: 405, category: m },
+    p406: { code: 406, category: m },
+    p407: { code: 407, category: m },
+    p408: { code: 408, category: m },
+    p409: { code: 409, category: m },
+    p410: { code: 410, category: m },
+    p411: { code: 411, category: m },
+    p412: { code: 412, category: m },
+    p413: { code: 413, category: m },
+    p414: { code: 414, category: m },
+    p415: { code: 415, category: m },
+    p416: { code: 416, category: m },
+    p417: { code: 417, category: m },
+    p418: { code: 418, category: m },
+    p419: { code: 419, category: m },
+    p420: { code: 420, category: m },
+    p421: { code: 421, category: m },
+    p422: { code: 422, category: m },
+    p423: { code: 423, category: m },
+    p424: { code: 424, category: m },
+    p425: { code: 425, category: m },
+    p426: { code: 426, category: m },
+    p427: { code: 427, category: m },
+    p428: { code: 428, category: m },
+    p429: { code: 429, category: m },
+    p430: { code: 430, category: m },
+    p431: { code: 431, category: m },
+    p432: { code: 432, category: m },
+    p433: { code: 433, category: m },
+    p434: { code: 434, category: m },
+    p435: { code: 435, category: m },
+    p436: { code: 436, category: m },
+    p437: { code: 437, category: m },
+    p438: { code: 438, category: m },
+    p439: { code: 439, category: m },
+    p440: { code: 440, category: m },
+    p441: { code: 441, category: m },
+    p442: { code: 442, category: m },
+    p443: { code: 443, category: m },
+    p444: { code: 444, category: m },
+    p445: { code: 445, category: m },
+    p446: { code: 446, category: m },
+    p447: { code: 447, category: m },
+    p448: { code: 448, category: m },
+    p449: { code: 449, category: m },
+    p450: { code: 450, category: m },
+    p451: { code: 451, category: m },
+    p452: { code: 452, category: m },
+    p453: { code: 453, category: m },
+    p454: { code: 454, category: m },
+    p455: { code: 455, category: m },
+    p456: { code: 456, category: m },
+    p457: { code: 457, category: m },
+    p458: { code: 458, category: m },
+    p459: { code: 459, category: m },
+    p460: { code: 460, category: m },
+    p461: { code: 461, category: m },
+    p462: { code: 462, category: m },
+    p463: { code: 463, category: m },
+    p464: { code: 464, category: m },
+    p465: { code: 465, category: m },
+    p466: { code: 466, category: m },
+    p467: { code: 467, category: m },
+    p468: { code: 468, category: m },
+    p469: { code: 469, category: m },
+    p470: { code: 470, category: m },
+    p471: { code: 471, category: m },
+    p472: { code: 472, category: m },
+    p473: { code: 473, category: m },
+    p474: { code: 474, category: m },
+    p475: { code: 475, category: m },
+    p476: { code: 476, category: m },
+    p477: { code: 477, category: m },
+    p478: { code: 478, category: m },
+    p479: { code: 479, category: m },
+    p480: { code: 480, category: m },
+    p481: { code: 481, category: m },
+    p482: { code: 482, category: m },
+    p483: { code: 483, category: m },
+    p484: { code: 484, category: m },
+    p485: { code: 485, category: m },
+    p486: { code: 486, category: m },
+    p487: { code: 487, category: m },
+    p488: { code: 488, category: m },
+    p489: { code: 489, category: m },
+    p490: { code: 490, category: m },
+    p491: { code: 491, category: m },
+    p492: { code: 492, category: m },
+    p493: { code: 493, category: m },
+    p494: { code: 494, category: m },
+    p495: { code: 495, category: m },
+    p496: { code: 496, category: m },
+    p497: { code: 497, category: m },
+    p498: { code: 498, category: m },
+    p499: { code: 499, category: m }
+};
+
+var AccessorProperty = Java.type("jdk.nashorn.internal.runtime.AccessorProperty");
+var SpillProperty    = Java.type("jdk.nashorn.internal.runtime.SpillProperty");
+
+Assert.assertTrue(Object.keys(fields).length === 3);
+Assert.assertTrue(Debug.map(fields).findProperty("p0").getClass() === AccessorProperty.class);
+Assert.assertTrue(Debug.map(fields).findProperty("p2").getClass() === AccessorProperty.class);
+
+Assert.assertTrue(Object.keys(spill).length === 500);
+Assert.assertTrue(Debug.map(spill).findProperty("p0").getClass() === SpillProperty.class);
+Assert.assertTrue(Debug.map(spill).findProperty("p499").getClass() === SpillProperty.class);
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/script/nosecurity/JDK-8080087.js
similarity index 68%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/script/nosecurity/JDK-8080087.js
index dfcad5a..4f07b6f 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/script/nosecurity/JDK-8080087.js
@@ -1,12 +1,10 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,9 +21,18 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+/**
+ * JDK-8080087: Nashorn $ENV.PWD is originally undefined
+ *
+ * This is to ensure that $ENV.PWD is correctly set on Windows as well as on all
+ * other platforms.
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
+if (typeof($ENV.PWD) === 'undefined') {
+    fail('$ENV.PWD is undefined')
 }
+
diff --git a/test/script/sandbox/interfaceimpl.js b/test/script/sandbox/interfaceimpl.js
index 0745318..17745fc 100644
--- a/test/script/sandbox/interfaceimpl.js
+++ b/test/script/sandbox/interfaceimpl.js
@@ -29,8 +29,8 @@
  * @security
  */
 
-var Window = Java.type("jdk.nashorn.api.scripting.Window");
-var WindowEventHandler = Java.type("jdk.nashorn.api.scripting.WindowEventHandler");
+var Window = Java.type("jdk.nashorn.api.scripting.test.Window");
+var WindowEventHandler = Java.type("jdk.nashorn.api.scripting.test.WindowEventHandler");
 
 var w = new Window();
 
diff --git a/test/script/sandbox/safeprops.js b/test/script/sandbox/safeprops.js
index dc12e74..67b700c 100644
--- a/test/script/sandbox/safeprops.js
+++ b/test/script/sandbox/safeprops.js
@@ -1,5 +1,5 @@
 /*
- * 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
diff --git a/test/script/trusted/JDK-8006529.js b/test/script/trusted/JDK-8006529.js
index 5f61807..7a4c094 100644
--- a/test/script/trusted/JDK-8006529.js
+++ b/test/script/trusted/JDK-8006529.js
@@ -120,7 +120,7 @@
 
 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(Context.class, ScriptEnvironment.class, CodeInstaller.class, Source.class, ErrorManager.class, boolean.class);
+var CompilerConstructor = Compiler.class.getMethod("forNoInstallerCompilation", Context.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
@@ -134,7 +134,7 @@
     var parser   = ParserConstructor.newInstance(env, source, ThrowErrorManager.class.newInstance());
     var func     = parseMethod.invoke(parser);
 
-    var compiler = CompilerConstructor.newInstance(ctxt, env, null, source, null, false);
+    var compiler = CompilerConstructor.invoke(null, ctxt, source, false);
 
     return compileMethod.invoke(compiler, func, phases);
 };
diff --git a/test/script/trusted/JDK-8025629.js b/test/script/trusted/JDK-8025629.js
index 609cfe8..f3f4cba 100644
--- a/test/script/trusted/JDK-8025629.js
+++ b/test/script/trusted/JDK-8025629.js
@@ -28,6 +28,6 @@
  * @run
  */
 
-load("classpath:jdk/nashorn/internal/runtime/resources/load_test.js")
+load("classpath:jdk/nashorn/internal/runtime/test/resources/load_test.js")
 
 Assert.assertEquals(loadedFunc("hello"), "HELLO");
diff --git a/test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java b/test/script/trusted/JDK-8067854.js
similarity index 65%
copy from test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java
copy to test/script/trusted/JDK-8067854.js
index d9a4455..487bd77 100644
--- a/test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java
+++ b/test/script/trusted/JDK-8067854.js
@@ -4,9 +4,7 @@
  *
  * This code is free software; you can redistribute 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.
+ * published by the Free Software Foundation.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@@ -23,15 +21,19 @@
  * questions.
  */
 
-package jdk.internal.dynalink.beans;
+/**
+ * JDK-8067854: bound java static method throws NPE when 'null' is used for this argument
+ *
+ * @test
+ * @run
+ */
 
-import jdk.nashorn.test.models.ClassLoaderAware;
-import org.testng.annotations.Test;
+getProp = java.lang.System.getProperty;
 
-@SuppressWarnings("javadoc")
-public class CallerSensitiveTest {
-    @Test
-    public void testCallerSensitive() {
-        BeansLinker.getLinkerForClass(ClassLoaderAware.class);
-    }
+// bind this and an argument. "null" for this as getProperty is a
+// static method of java.lang.System
+getHome = Function.prototype.bind.call(getProp, null, "java.home");
+
+if (getHome() != getProp("java.home")) {
+    fail("getHome() failed to get java.home");
 }
diff --git a/test/script/trusted/JDK-8087292.js b/test/script/trusted/JDK-8087292.js
new file mode 100644
index 0000000..2973eb3
--- /dev/null
+++ b/test/script/trusted/JDK-8087292.js
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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-8087292: nashorn should have a "fail-fast" option for scripting, analog to bash "set -e"
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+function tryExec() {
+    try {
+        `java`
+    } catch (e) {
+        print(e);
+    }
+
+    // make sure we got non-zero ("failure") exit code!
+    if ($EXIT == 0) {
+        print("Error: expected $EXIT code to be non-zero");
+    }
+}
+
+// no exception now!
+tryExec();
+
+// turn on error with non-zero exit code
+$EXEC.throwOnError = true;
+tryExec();
+
+// no exception after this
+$EXEC.throwOnError = false;
+tryExec();
diff --git a/test/script/trusted/JDK-8087292.js.EXPECTED b/test/script/trusted/JDK-8087292.js.EXPECTED
new file mode 100644
index 0000000..60c5f80
--- /dev/null
+++ b/test/script/trusted/JDK-8087292.js.EXPECTED
@@ -0,0 +1 @@
+RangeError: $EXEC returned non-zero exit code: 1

diff --git a/test/script/trusted/classfilter.js.EXPECTED b/test/script/trusted/classfilter.js.EXPECTED
index 43d6303..365df61 100644
--- a/test/script/trusted/classfilter.js.EXPECTED
+++ b/test/script/trusted/classfilter.js.EXPECTED
@@ -4,7 +4,18 @@
 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.out.println evalutes to [jdk.internal.dynalink.beans.OverloadedDynamicMethod
+ void java.io.PrintStream.println()
+ void java.io.PrintStream.println(boolean)
+ void java.io.PrintStream.println(char)
+ void java.io.PrintStream.println(char[])
+ void java.io.PrintStream.println(double)
+ void java.io.PrintStream.println(float)
+ void java.io.PrintStream.println(int)
+ void java.io.PrintStream.println(long)
+ void java.io.PrintStream.println(Object)
+ void java.io.PrintStream.println(String)
+]
 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
diff --git a/test/src/META-INF/services/java.sql.Driver b/test/src/META-INF/services/java.sql.Driver
index 295fe48..d1bb7d3 100644
--- a/test/src/META-INF/services/java.sql.Driver
+++ b/test/src/META-INF/services/java.sql.Driver
@@ -1 +1 @@
-jdk.nashorn.api.NashornSQLDriver
+jdk.nashorn.api.test.NashornSQLDriver
diff --git a/test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java b/test/src/jdk/internal/dynalink/beans/test/CallerSensitiveTest.java
similarity index 94%
rename from test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java
rename to test/src/jdk/internal/dynalink/beans/test/CallerSensitiveTest.java
index d9a4455..2a6b746 100644
--- a/test/src/jdk/internal/dynalink/beans/CallerSensitiveTest.java
+++ b/test/src/jdk/internal/dynalink/beans/test/CallerSensitiveTest.java
@@ -23,8 +23,9 @@
  * questions.
  */
 
-package jdk.internal.dynalink.beans;
+package jdk.internal.dynalink.beans.test;
 
+import jdk.internal.dynalink.beans.BeansLinker;
 import jdk.nashorn.test.models.ClassLoaderAware;
 import org.testng.annotations.Test;
 
diff --git a/test/src/jdk/nashorn/api/javaaccess/ArrayConversionTest.java b/test/src/jdk/nashorn/api/javaaccess/test/ArrayConversionTest.java
similarity index 99%
rename from test/src/jdk/nashorn/api/javaaccess/ArrayConversionTest.java
rename to test/src/jdk/nashorn/api/javaaccess/test/ArrayConversionTest.java
index 1da767b..a7a17a2 100644
--- a/test/src/jdk/nashorn/api/javaaccess/ArrayConversionTest.java
+++ b/test/src/jdk/nashorn/api/javaaccess/test/ArrayConversionTest.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.api.javaaccess;
+package jdk.nashorn.api.javaaccess.test;
 
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertFalse;
diff --git a/test/src/jdk/nashorn/api/javaaccess/BooleanAccessTest.java b/test/src/jdk/nashorn/api/javaaccess/test/BooleanAccessTest.java
similarity index 96%
rename from test/src/jdk/nashorn/api/javaaccess/BooleanAccessTest.java
rename to test/src/jdk/nashorn/api/javaaccess/test/BooleanAccessTest.java
index 234484f..8030419 100644
--- a/test/src/jdk/nashorn/api/javaaccess/BooleanAccessTest.java
+++ b/test/src/jdk/nashorn/api/javaaccess/test/BooleanAccessTest.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.api.javaaccess;
+package jdk.nashorn.api.javaaccess.test;
 
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertTrue;
@@ -38,8 +38,8 @@
 
 /**
  * @test
- * @build jdk.nashorn.api.javaaccess.SharedObject jdk.nashorn.api.javaaccess.Person jdk.nashorn.api.javaaccess.BooleanAccessTest
- * @run testng/othervm jdk.nashorn.api.javaaccess.BooleanAccessTest
+ * @build jdk.nashorn.api.javaaccess.test.SharedObject jdk.nashorn.api.javaaccess.test.Person jdk.nashorn.api.javaaccess.test.BooleanAccessTest
+ * @run testng/othervm jdk.nashorn.api.javaaccess.test.BooleanAccessTest
  */
 @SuppressWarnings("javadoc")
 public class BooleanAccessTest {
@@ -57,7 +57,7 @@
         e = m.getEngineByName("nashorn");
         o = new SharedObject();
         e.put("o", o);
-        e.eval("var SharedObject = Packages.jdk.nashorn.api.javaaccess.SharedObject;");
+        e.eval("var SharedObject = Packages.jdk.nashorn.api.javaaccess.test.SharedObject;");
     }
 
     @AfterClass
diff --git a/test/src/jdk/nashorn/api/javaaccess/ConsStringTest.java b/test/src/jdk/nashorn/api/javaaccess/test/ConsStringTest.java
similarity index 98%
rename from test/src/jdk/nashorn/api/javaaccess/ConsStringTest.java
rename to test/src/jdk/nashorn/api/javaaccess/test/ConsStringTest.java
index 2b12b04..db8794b 100644
--- a/test/src/jdk/nashorn/api/javaaccess/ConsStringTest.java
+++ b/test/src/jdk/nashorn/api/javaaccess/test/ConsStringTest.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.api.javaaccess;
+package jdk.nashorn.api.javaaccess.test;
 
 import static org.testng.AssertJUnit.assertEquals;
 import java.util.HashMap;
diff --git a/test/src/jdk/nashorn/api/javaaccess/MethodAccessTest.java b/test/src/jdk/nashorn/api/javaaccess/test/MethodAccessTest.java
similarity index 98%
rename from test/src/jdk/nashorn/api/javaaccess/MethodAccessTest.java
rename to test/src/jdk/nashorn/api/javaaccess/test/MethodAccessTest.java
index 8bac7e6..ba3460d 100644
--- a/test/src/jdk/nashorn/api/javaaccess/MethodAccessTest.java
+++ b/test/src/jdk/nashorn/api/javaaccess/test/MethodAccessTest.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.api.javaaccess;
+package jdk.nashorn.api.javaaccess.test;
 
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertTrue;
@@ -41,8 +41,8 @@
 
 /**
  * @test
- * @build jdk.nashorn.api.javaaccess.SharedObject jdk.nashorn.api.javaaccess.Person jdk.nashorn.api.javaaccess.MethodAccessTest
- * @run testng/othervm jdk.nashorn.api.javaaccess.MethodAccessTest
+ * @build jdk.nashorn.api.javaaccess.test.SharedObject jdk.nashorn.api.javaaccess.test.Person jdk.nashorn.api.javaaccess.test.MethodAccessTest
+ * @run testng/othervm jdk.nashorn.api.javaaccess.test.MethodAccessTest
  */
 @SuppressWarnings("javadoc")
 public class MethodAccessTest {
@@ -61,8 +61,8 @@
         o = new SharedObject();
         o.setEngine(e);
         e.put("o", o);
-        e.eval("var SharedObject = Packages.jdk.nashorn.api.javaaccess.SharedObject;");
-        e.eval("var Person = Packages.jdk.nashorn.api.javaaccess.Person;");
+        e.eval("var SharedObject = Packages.jdk.nashorn.api.javaaccess.test.SharedObject;");
+        e.eval("var Person = Packages.jdk.nashorn.api.javaaccess.test.Person;");
     }
 
     @AfterClass
@@ -338,13 +338,13 @@
 
     @Test
     public void accessDefaultConstructor() throws ScriptException {
-        e.eval("var dc = new Packages.jdk.nashorn.api.javaaccess.Person()");
+        e.eval("var dc = new Packages.jdk.nashorn.api.javaaccess.test.Person()");
         assertEquals(new Person(), e.get("dc"));
     }
 
     @Test
     public void accessCustomConstructor() throws ScriptException {
-        e.eval("var cc = new Packages.jdk.nashorn.api.javaaccess.Person(17)");
+        e.eval("var cc = new Packages.jdk.nashorn.api.javaaccess.test.Person(17)");
         assertEquals(new Person(17), e.get("cc"));
     }
 
diff --git a/test/src/jdk/nashorn/api/javaaccess/NumberAccessTest.java b/test/src/jdk/nashorn/api/javaaccess/test/NumberAccessTest.java
similarity index 99%
rename from test/src/jdk/nashorn/api/javaaccess/NumberAccessTest.java
rename to test/src/jdk/nashorn/api/javaaccess/test/NumberAccessTest.java
index fd4ab9d..882ed06 100644
--- a/test/src/jdk/nashorn/api/javaaccess/NumberAccessTest.java
+++ b/test/src/jdk/nashorn/api/javaaccess/test/NumberAccessTest.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.api.javaaccess;
+package jdk.nashorn.api.javaaccess.test;
 
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertTrue;
@@ -38,8 +38,8 @@
 
 /**
  * @test
- * @build jdk.nashorn.api.javaaccess.SharedObject jdk.nashorn.api.javaaccess.Person jdk.nashorn.api.javaaccess.NumberAccessTest
- * @run testng/othervm jdk.nashorn.api.javaaccess.NumberAccessTest
+ * @build jdk.nashorn.api.javaaccess.test.SharedObject jdk.nashorn.api.javaaccess.test.Person jdk.nashorn.api.javaaccess.test.NumberAccessTest
+ * @run testng/othervm jdk.nashorn.api.javaaccess.test.NumberAccessTest
  */
 @SuppressWarnings("javadoc")
 public class NumberAccessTest {
@@ -57,7 +57,7 @@
         e = m.getEngineByName("nashorn");
         o = new SharedObject();
         e.put("o", o);
-        e.eval("var SharedObject = Packages.jdk.nashorn.api.javaaccess.SharedObject;");
+        e.eval("var SharedObject = Packages.jdk.nashorn.api.javaaccess.test.SharedObject;");
     }
 
     @AfterClass
diff --git a/test/src/jdk/nashorn/api/javaaccess/NumberBoxingTest.java b/test/src/jdk/nashorn/api/javaaccess/test/NumberBoxingTest.java
similarity index 98%
rename from test/src/jdk/nashorn/api/javaaccess/NumberBoxingTest.java
rename to test/src/jdk/nashorn/api/javaaccess/test/NumberBoxingTest.java
index 40db684..9d5a2f7 100644
--- a/test/src/jdk/nashorn/api/javaaccess/NumberBoxingTest.java
+++ b/test/src/jdk/nashorn/api/javaaccess/test/NumberBoxingTest.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.api.javaaccess;
+package jdk.nashorn.api.javaaccess.test;
 
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.AssertJUnit.assertTrue;
@@ -37,8 +37,8 @@
 
 /**
  * @test
- * @build jdk.nashorn.api.javaaccess.SharedObject jdk.nashorn.api.javaaccess.Person jdk.nashorn.api.javaaccess.NumberBoxingTest
- * @run testng/othervm jdk.nashorn.api.javaaccess.NumberBoxingTest
+ * @build jdk.nashorn.api.javaaccess.test.SharedObject jdk.nashorn.api.javaaccess.test.Person jdk.nashorn.api.javaaccess.test.NumberBoxingTest
+ * @run testng/othervm jdk.nashorn.api.javaaccess.test.NumberBoxingTest
  */
 @SuppressWarnings("javadoc")
 public class NumberBoxingTest {
@@ -56,7 +56,7 @@
         e = m.getEngineByName("nashorn");
         o = new SharedObject();
         e.put("o", o);
-        e.eval("var SharedObject = Packages.jdk.nashorn.api.javaaccess.SharedObject;");
+        e.eval("var SharedObject = Packages.jdk.nashorn.api.javaaccess.test.SharedObject;");
     }
 
     @AfterClass
diff --git a/test/src/jdk/nashorn/api/javaaccess/ObjectAccessTest.java b/test/src/jdk/nashorn/api/javaaccess/test/ObjectAccessTest.java
similarity index 94%
rename from test/src/jdk/nashorn/api/javaaccess/ObjectAccessTest.java
rename to test/src/jdk/nashorn/api/javaaccess/test/ObjectAccessTest.java
index 00798a4..80a325e 100644
--- a/test/src/jdk/nashorn/api/javaaccess/ObjectAccessTest.java
+++ b/test/src/jdk/nashorn/api/javaaccess/test/ObjectAccessTest.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.api.javaaccess;
+package jdk.nashorn.api.javaaccess.test;
 
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
@@ -37,8 +37,8 @@
 
 /**
  * @test
- * @build jdk.nashorn.api.javaaccess.SharedObject jdk.nashorn.api.javaaccess.Person jdk.nashorn.api.javaaccess.ObjectAccessTest
- * @run testng/othervm jdk.nashorn.api.javaaccess.ObjectAccessTest
+ * @build jdk.nashorn.api.javaaccess.test.SharedObject jdk.nashorn.api.javaaccess.test.Person jdk.nashorn.api.javaaccess.test.ObjectAccessTest
+ * @run testng/othervm jdk.nashorn.api.javaaccess.test.ObjectAccessTest
  */
 @SuppressWarnings("javadoc")
 public class ObjectAccessTest {
@@ -56,8 +56,8 @@
         e = m.getEngineByName("nashorn");
         o = new SharedObject();
         e.put("o", o);
-        e.eval("var SharedObject = Packages.jdk.nashorn.api.javaaccess.SharedObject;");
-        e.eval("var Person = Packages.jdk.nashorn.api.javaaccess.Person;");
+        e.eval("var SharedObject = Packages.jdk.nashorn.api.javaaccess.test.SharedObject;");
+        e.eval("var Person = Packages.jdk.nashorn.api.javaaccess.test.Person;");
     }
 
     @AfterClass
@@ -80,7 +80,7 @@
         e.eval("var p_object_array = o.publicObjectArray;");
         assertEquals(o.publicObjectArray[0], e.eval("o.publicObjectArray[0]"));
         assertArrayEquals(o.publicObjectArray, (Object[])e.get("p_object_array"));
-        e.eval("var t_object_arr = new (Java.type(\"jdk.nashorn.api.javaaccess.Person[]\"))(3);" +
+        e.eval("var t_object_arr = new (Java.type(\"jdk.nashorn.api.javaaccess.test.Person[]\"))(3);" +
                 "t_object_arr[0] = new Person(100);" +
                 "t_object_arr[1] = new Person(120);" +
                 "t_object_arr[2] = new Person(140);" +
@@ -104,7 +104,7 @@
         e.eval("var ps_object_array = SharedObject.publicStaticObjectArray;");
         assertEquals(SharedObject.publicStaticObjectArray[0], e.eval("SharedObject.publicStaticObjectArray[0]"));
         assertArrayEquals(SharedObject.publicStaticObjectArray, (Object[])e.get("ps_object_array"));
-        e.eval("var ts_object_arr = new (Java.type(\"jdk.nashorn.api.javaaccess.Person[]\"))(3);" +
+        e.eval("var ts_object_arr = new (Java.type(\"jdk.nashorn.api.javaaccess.test.Person[]\"))(3);" +
                 "ts_object_arr[0] = new Person(100);" +
                 "ts_object_arr[1] = new Person(120);" +
                 "ts_object_arr[2] = new Person(140);" +
@@ -128,7 +128,7 @@
         e.eval("var pf_object_array = o.publicFinalObjectArray;");
         assertEquals(o.publicFinalObjectArray[0], e.eval("o.publicFinalObjectArray[0]"));
         assertArrayEquals(o.publicFinalObjectArray, (Object[])e.get("pf_object_array"));
-        e.eval("var tf_object_arr = new (Java.type(\"jdk.nashorn.api.javaaccess.Person[]\"))(3);" +
+        e.eval("var tf_object_arr = new (Java.type(\"jdk.nashorn.api.javaaccess.test.Person[]\"))(3);" +
                 "tf_object_arr[0] = new Person(100);" +
                 "tf_object_arr[1] = new Person(120);" +
                 "tf_object_arr[2] = new Person(140);" +
@@ -152,7 +152,7 @@
         e.eval("var psf_object_array = SharedObject.publicStaticFinalObjectArray;");
         assertEquals(SharedObject.publicStaticFinalObjectArray[0], e.eval("SharedObject.publicStaticFinalObjectArray[0]"));
         assertArrayEquals(SharedObject.publicStaticFinalObjectArray, (Object[])e.get("psf_object_array"));
-        e.eval("var tsf_object_arr = new (Java.type(\"jdk.nashorn.api.javaaccess.Person[]\"))(3);" +
+        e.eval("var tsf_object_arr = new (Java.type(\"jdk.nashorn.api.javaaccess.test.Person[]\"))(3);" +
                 "tsf_object_arr[0] = new Person(100);" +
                 "tsf_object_arr[1] = new Person(120);" +
                 "tsf_object_arr[2] = new Person(140);" +
diff --git a/test/src/jdk/nashorn/api/javaaccess/Person.java b/test/src/jdk/nashorn/api/javaaccess/test/Person.java
similarity index 97%
rename from test/src/jdk/nashorn/api/javaaccess/Person.java
rename to test/src/jdk/nashorn/api/javaaccess/test/Person.java
index 32b1c9b..3e563b1 100644
--- a/test/src/jdk/nashorn/api/javaaccess/Person.java
+++ b/test/src/jdk/nashorn/api/javaaccess/test/Person.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.api.javaaccess;
+package jdk.nashorn.api.javaaccess.test;
 
 @SuppressWarnings("javadoc")
 public class Person {
diff --git a/test/src/jdk/nashorn/api/javaaccess/SharedObject.java b/test/src/jdk/nashorn/api/javaaccess/test/SharedObject.java
similarity index 99%
rename from test/src/jdk/nashorn/api/javaaccess/SharedObject.java
rename to test/src/jdk/nashorn/api/javaaccess/test/SharedObject.java
index 93c93e1..3c41ac1 100644
--- a/test/src/jdk/nashorn/api/javaaccess/SharedObject.java
+++ b/test/src/jdk/nashorn/api/javaaccess/test/SharedObject.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.api.javaaccess;
+package jdk.nashorn.api.javaaccess.test;
 
 import javax.script.Invocable;
 import javax.script.ScriptEngine;
diff --git a/test/src/jdk/nashorn/api/javaaccess/StringAccessTest.java b/test/src/jdk/nashorn/api/javaaccess/test/StringAccessTest.java
similarity index 96%
rename from test/src/jdk/nashorn/api/javaaccess/StringAccessTest.java
rename to test/src/jdk/nashorn/api/javaaccess/test/StringAccessTest.java
index 1e0a96a..909ddb4 100644
--- a/test/src/jdk/nashorn/api/javaaccess/StringAccessTest.java
+++ b/test/src/jdk/nashorn/api/javaaccess/test/StringAccessTest.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.api.javaaccess;
+package jdk.nashorn.api.javaaccess.test;
 
 import static org.testng.AssertJUnit.assertEquals;
 import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
@@ -37,8 +37,8 @@
 
 /**
  * @test
- * @build jdk.nashorn.api.javaaccess.SharedObject jdk.nashorn.api.javaaccess.Person jdk.nashorn.api.javaaccess.StringAccessTest
- * @run testng/othervm jdk.nashorn.api.javaaccess.StringAccessTest
+ * @build jdk.nashorn.api.javaaccess.test.SharedObject jdk.nashorn.api.javaaccess.test.Person jdk.nashorn.api.javaaccess.test.StringAccessTest
+ * @run testng/othervm jdk.nashorn.api.javaaccess.test.StringAccessTest
  */
 @SuppressWarnings("javadoc")
 public class StringAccessTest {
@@ -56,7 +56,7 @@
         e = m.getEngineByName("nashorn");
         o = new SharedObject();
         e.put("o", o);
-        e.eval("var SharedObject = Packages.jdk.nashorn.api.javaaccess.SharedObject;");
+        e.eval("var SharedObject = Packages.jdk.nashorn.api.javaaccess.test.SharedObject;");
     }
 
     @AfterClass
diff --git a/test/src/jdk/nashorn/api/scripting/InvocableTest.java b/test/src/jdk/nashorn/api/scripting/test/InvocableTest.java
similarity index 99%
rename from test/src/jdk/nashorn/api/scripting/InvocableTest.java
rename to test/src/jdk/nashorn/api/scripting/test/InvocableTest.java
index 4e44a29..bba4ce5 100644
--- a/test/src/jdk/nashorn/api/scripting/InvocableTest.java
+++ b/test/src/jdk/nashorn/api/scripting/test/InvocableTest.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+package jdk.nashorn.api.scripting.test;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.fail;
diff --git a/test/src/jdk/nashorn/api/scripting/test/JSONCompatibleTest.java b/test/src/jdk/nashorn/api/scripting/test/JSONCompatibleTest.java
new file mode 100644
index 0000000..0b52d9d
--- /dev/null
+++ b/test/src/jdk/nashorn/api/scripting/test/JSONCompatibleTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+import jdk.nashorn.api.scripting.JSObject;
+import jdk.nashorn.api.scripting.NashornScriptEngine;
+import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class JSONCompatibleTest {
+
+    /**
+     * Wrap a top-level array as a list.
+     */
+    @Test
+    public void testWrapArray() throws ScriptException {
+        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
+        final Object val = engine.eval("Java.asJSONCompatible([1, 2, 3])");
+        assertEquals(asList(val), Arrays.asList(1, 2, 3));
+    }
+
+    /**
+     * Wrap an embedded array as a list.
+     */
+    @Test
+    public void testWrapObjectWithArray() throws ScriptException {
+        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
+        final Object val = engine.eval("Java.asJSONCompatible({x: [1, 2, 3]})");
+        assertEquals(asList(asMap(val).get("x")), Arrays.asList(1, 2, 3));
+    }
+
+    /**
+     * Check it all works transitively several more levels down.
+     */
+    @Test
+    public void testDeepWrapping() throws ScriptException {
+        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
+        final Object val = engine.eval("Java.asJSONCompatible({x: [1, {y: [2, {z: [3]}]}, [4, 5]]})");
+        final Map<String, Object> root = asMap(val);
+        final List<Object> x = asList(root.get("x"));
+        assertEquals(x.get(0), 1);
+        final Map<String, Object> x1 = asMap(x.get(1));
+        final List<Object> y = asList(x1.get("y"));
+        assertEquals(y.get(0), 2);
+        final Map<String, Object> y1 = asMap(y.get(1));
+        assertEquals(asList(y1.get("z")), Arrays.asList(3));
+        assertEquals(asList(x.get(2)), Arrays.asList(4, 5));
+    }
+
+    /**
+     * Ensure that the old behaviour (every object is a Map) is unchanged.
+     */
+    @Test
+    public void testNonWrapping() throws ScriptException {
+        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
+        final Object val = engine.eval("({x: [1, {y: [2, {z: [3]}]}, [4, 5]]})");
+        final Map<String, Object> root = asMap(val);
+        final Map<String, Object> x = asMap(root.get("x"));
+        assertEquals(x.get("0"), 1);
+        final Map<String, Object> x1 = asMap(x.get("1"));
+        final Map<String, Object> y = asMap(x1.get("y"));
+        assertEquals(y.get("0"), 2);
+        final Map<String, Object> y1 = asMap(y.get("1"));
+        final Map<String, Object> z = asMap(y1.get("z"));
+        assertEquals(z.get("0"), 3);
+        final Map<String, Object> x2 = asMap(x.get("2"));
+        assertEquals(x2.get("0"), 4);
+        assertEquals(x2.get("1"), 5);
+    }
+
+    @SuppressWarnings("unchecked")
+    private static List<Object> asList(final Object obj) {
+        assertJSObject(obj);
+        Assert.assertTrue(obj instanceof List);
+        return (List)obj;
+    }
+
+    @SuppressWarnings("unchecked")
+    private static Map<String, Object> asMap(final Object obj) {
+        assertJSObject(obj);
+        Assert.assertTrue(obj instanceof Map);
+        return (Map)obj;
+    }
+
+    private static void assertJSObject(final Object obj) {
+        assertTrue(obj instanceof JSObject);
+    }
+}
diff --git a/test/src/jdk/nashorn/api/scripting/MultipleEngineTest.java b/test/src/jdk/nashorn/api/scripting/test/MultipleEngineTest.java
similarity index 94%
rename from test/src/jdk/nashorn/api/scripting/MultipleEngineTest.java
rename to test/src/jdk/nashorn/api/scripting/test/MultipleEngineTest.java
index 218deff..76982fa 100644
--- a/test/src/jdk/nashorn/api/scripting/MultipleEngineTest.java
+++ b/test/src/jdk/nashorn/api/scripting/test/MultipleEngineTest.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+package jdk.nashorn.api.scripting.test;
 
 import javax.script.ScriptEngine;
 import javax.script.ScriptEngineManager;
@@ -35,7 +35,7 @@
  * independently.
  *
  * @test
- * @run testng jdk.nashorn.api.scripting.MultipleEngineTest
+ * @run testng jdk.nashorn.api.scripting.test.MultipleEngineTest
  */
 @SuppressWarnings("javadoc")
 public class MultipleEngineTest {
diff --git a/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java b/test/src/jdk/nashorn/api/scripting/test/PluggableJSObjectTest.java
similarity index 77%
rename from test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java
rename to test/src/jdk/nashorn/api/scripting/test/PluggableJSObjectTest.java
index b277bde..918e931 100644
--- a/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java
+++ b/test/src/jdk/nashorn/api/scripting/test/PluggableJSObjectTest.java
@@ -23,10 +23,11 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+package jdk.nashorn.api.scripting.test;
 
 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.IntBuffer;
@@ -34,8 +35,11 @@
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Set;
+import javax.script.Invocable;
 import javax.script.ScriptEngine;
 import javax.script.ScriptEngineManager;
+import jdk.nashorn.api.scripting.AbstractJSObject;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import org.testng.annotations.Test;
 
 /**
@@ -109,6 +113,35 @@
         }
     }
 
+    // @bug 8062030: Nashorn bug retrieving array property after key string concatenation
+    @Test
+    // ConsString attribute access on a JSObject
+    public void consStringTest() {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        try {
+            final MapWrapperObject obj = new MapWrapperObject();
+            e.put("obj", obj);
+            e.put("f", "f");
+            e.eval("obj[f + 'oo'] = 'bar';");
+
+            assertEquals(obj.getMap().get("foo"), "bar");
+            assertEquals(e.eval("obj[f + 'oo']"), "bar");
+            assertEquals(e.eval("obj['foo']"), "bar");
+            assertEquals(e.eval("f + 'oo' in obj"), Boolean.TRUE);
+            assertEquals(e.eval("'foo' in obj"), Boolean.TRUE);
+            e.eval("delete obj[f + 'oo']");
+            assertFalse(obj.getMap().containsKey("foo"));
+            assertEquals(e.eval("obj[f + 'oo']"), null);
+            assertEquals(e.eval("obj['foo']"), null);
+            assertEquals(e.eval("f + 'oo' in obj"), Boolean.FALSE);
+            assertEquals(e.eval("'foo' in obj"), Boolean.FALSE);
+        } catch (final Exception exp) {
+            exp.printStackTrace();
+            fail(exp.getMessage());
+        }
+    }
+
     public static class BufferObject extends AbstractJSObject {
         private final IntBuffer buf;
 
@@ -256,4 +289,23 @@
             fail(exp.getMessage());
         }
     }
+
+    // @bug 8137258: JSObjectLinker and BrowserJSObjectLinker should not expose internal JS objects
+    @Test
+    public void hidingInternalObjectsForJSObjectTest() throws Exception {
+        final ScriptEngineManager engineManager = new ScriptEngineManager();
+        final ScriptEngine e = engineManager.getEngineByName("nashorn");
+
+        final String code = "function func(obj) { obj.foo = [5, 5]; obj.bar = {} }";
+        e.eval(code);
+
+        // call the exposed function but pass user defined JSObject impl as argument
+        ((Invocable)e).invokeFunction("func", new AbstractJSObject() {
+            @Override
+            public void setMember(final String name, final Object value) {
+                // make sure that wrapped objects are passed (and not internal impl. objects)
+                assertTrue(value.getClass() == ScriptObjectMirror.class);
+            }
+        });
+    }
 }
diff --git a/test/src/jdk/nashorn/api/scripting/ScopeTest.java b/test/src/jdk/nashorn/api/scripting/test/ScopeTest.java
similarity index 77%
rename from test/src/jdk/nashorn/api/scripting/ScopeTest.java
rename to test/src/jdk/nashorn/api/scripting/test/ScopeTest.java
index 4e1dfe7..05b614a 100644
--- a/test/src/jdk/nashorn/api/scripting/ScopeTest.java
+++ b/test/src/jdk/nashorn/api/scripting/test/ScopeTest.java
@@ -22,19 +22,25 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package jdk.nashorn.api.scripting;
+package jdk.nashorn.api.scripting.test;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 import javax.script.Bindings;
+import javax.script.Invocable;
 import javax.script.ScriptContext;
 import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
 import javax.script.ScriptEngineManager;
 import javax.script.ScriptException;
 import javax.script.SimpleBindings;
 import javax.script.SimpleScriptContext;
+import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
+import jdk.nashorn.api.scripting.URLReader;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
@@ -706,4 +712,203 @@
         }
     }
 
+    // @bug 8071678: NashornScriptEngine returns javax.script.ScriptContext instance
+    // with get/setAttribute methods insonsistent for GLOBAL_SCOPE
+    @Test
+    public void testGlobalScopeSearch() throws Exception {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        final ScriptContext c = e.getContext();
+        c.setAttribute("name1234", "value", ScriptContext.GLOBAL_SCOPE);
+        assertEquals(c.getAttribute("name1234"), "value");
+        assertEquals(c.getAttributesScope("name1234"),
+            ScriptContext.GLOBAL_SCOPE);
+    }
+
+    // @bug 8071594: NashornScriptEngine returns javax.script.ScriptContext instance
+    // which doesn't completely conform to the spec regarding exceptions throwing
+    @Test
+    public void testScriptContext_NPE_IAE() throws Exception {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        final ScriptContext c = e.getContext();
+        try {
+            c.getAttribute("");
+            throw new AssertionError("should have thrown IAE");
+        } catch (IllegalArgumentException iae1) {}
+
+        try {
+            c.getAttribute(null);
+            throw new AssertionError("should have thrown NPE");
+        } catch (NullPointerException npe1) {}
+
+        try {
+            c.getAttribute("", ScriptContext.ENGINE_SCOPE);
+            throw new AssertionError("should have thrown IAE");
+        } catch (IllegalArgumentException iae2) {}
+
+        try {
+            c.getAttribute(null, ScriptContext.ENGINE_SCOPE);
+            throw new AssertionError("should have thrown NPE");
+        } catch (NullPointerException npe2) {}
+
+        try {
+            c.removeAttribute("", ScriptContext.ENGINE_SCOPE);
+            throw new AssertionError("should have thrown IAE");
+        } catch (IllegalArgumentException iae3) {}
+
+        try {
+            c.removeAttribute(null, ScriptContext.ENGINE_SCOPE);
+            throw new AssertionError("should have thrown NPE");
+        } catch (NullPointerException npe3) {}
+
+        try {
+            c.setAttribute("", "value", ScriptContext.ENGINE_SCOPE);
+            throw new AssertionError("should have thrown IAE");
+        } catch (IllegalArgumentException iae4) {}
+
+        try {
+            c.setAttribute(null, "value", ScriptContext.ENGINE_SCOPE);
+            throw new AssertionError("should have thrown NPE");
+        } catch (NullPointerException npe4) {}
+
+        try {
+            c.getAttributesScope("");
+            throw new AssertionError("should have thrown IAE");
+        } catch (IllegalArgumentException iae5) {}
+
+        try {
+            c.getAttributesScope(null);
+            throw new AssertionError("should have thrown NPE");
+        } catch (NullPointerException npe5) {}
+    }
+
+    public static class RecursiveEval {
+        private final ScriptEngineFactory factory = new NashornScriptEngineFactory();
+        private final ScriptEngine engine = factory.getScriptEngine();
+        private final Bindings engineBindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
+
+        public void program() throws ScriptException {
+            ScriptContext sc = new SimpleScriptContext();
+            Bindings global = new SimpleBindings();
+            sc.setBindings(global, ScriptContext.GLOBAL_SCOPE);
+            sc.setBindings(engineBindings, ScriptContext.ENGINE_SCOPE);
+            global.put("text", "programText");
+            String value = engine.eval("text", sc).toString();
+            Assert.assertEquals(value, "programText");
+            engine.put("program", this);
+            engine.eval("program.method()");
+            // eval again from here!
+            value = engine.eval("text", sc).toString();
+            Assert.assertEquals(value, "programText");
+        }
+
+        public void method() throws ScriptException {
+            // a context with a new global bindings, same engine bindings
+            final ScriptContext sc = new SimpleScriptContext();
+            final Bindings global = new SimpleBindings();
+            sc.setBindings(global, ScriptContext.GLOBAL_SCOPE);
+            sc.setBindings(engineBindings, ScriptContext.ENGINE_SCOPE);
+            global.put("text", "methodText");
+            String value = engine.eval("text", sc).toString();
+            Assert.assertEquals(value, "methodText");
+        }
+    }
+
+    // @bug 8081609: engine.eval call from a java method which
+    // was called from a previous engine.eval results in wrong
+    // ScriptContext being used.
+    @Test
+    public void recursiveEvalCallScriptContextTest() throws ScriptException {
+        new RecursiveEval().program();
+    }
+
+    private static final String VAR_NAME = "myvar";
+
+    private static boolean lookupVar(final ScriptEngine engine, final String varName) {
+        try {
+            engine.eval(varName);
+            return true;
+        } catch (final ScriptException se) {
+            return false;
+        }
+    }
+
+    // @bug 8136544: Call site switching to megamorphic causes incorrect property read
+    @Test
+    public void megamorphicPropertyReadTest() throws ScriptException {
+        final NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+        final ScriptEngine engine = factory.getScriptEngine();
+        final Bindings scope = engine.getBindings(ScriptContext.ENGINE_SCOPE);
+        boolean ret;
+
+        // Why 16 is the upper limit of this loop? The default nashorn dynalink megamorphic threshold is 16.
+        // See jdk.nashorn.internal.runtime.linker.Bootstrap.NASHORN_DEFAULT_UNSTABLE_RELINK_THRESHOLD
+        // We do, 'eval' of the same in this loop twice. So, 16*2 = 32 times that callsite in the script
+        // is exercised - much beyond the default megamorphic threshold.
+
+        for (int i = 0; i < 16; i++) {
+            scope.remove(VAR_NAME);
+            ret = lookupVar(engine, VAR_NAME);
+            assertFalse(ret, "Expected false in iteration " + i);
+            scope.put(VAR_NAME, "foo");
+            ret = lookupVar(engine, VAR_NAME);
+            assertTrue(ret, "Expected true in iteration " + i);
+        }
+    }
+
+    // @bug 8138616: invokeFunction fails if function calls a function defined in GLOBAL_SCOPE
+    @Test
+    public void invokeFunctionInGlobalScopeTest() throws Exception {
+         final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
+         final ScriptContext ctxt = engine.getContext();
+
+         // define a function called "func"
+         engine.eval("func = function() { return 42 }");
+
+         // move ENGINE_SCOPE Bindings to GLOBAL_SCOPE
+         ctxt.setBindings(ctxt.getBindings(ScriptContext.ENGINE_SCOPE), ScriptContext.GLOBAL_SCOPE);
+
+         // create a new Bindings and set as ENGINE_SCOPE
+         ctxt.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
+
+         // define new function that calls "func" now in GLOBAL_SCOPE
+         engine.eval("newfunc = function() { return func() }");
+
+         // call "newfunc" and check the return value
+         Object value = ((Invocable)engine).invokeFunction("newfunc");
+         assertTrue(((Number)value).intValue() == 42);
+    }
+
+
+    // @bug 8138616: invokeFunction fails if function calls a function defined in GLOBAL_SCOPE
+    // variant of above that replaces default ScriptContext of the engine with a fresh instance!
+    @Test
+    public void invokeFunctionInGlobalScopeTest2() throws Exception {
+         final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
+
+         // create a new ScriptContext instance
+         final ScriptContext ctxt = new SimpleScriptContext();
+         // set it as 'default' ScriptContext
+         engine.setContext(ctxt);
+
+         // create a new Bindings and set as ENGINE_SCOPE
+         ctxt.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
+
+         // define a function called "func"
+         engine.eval("func = function() { return 42 }");
+
+         // move ENGINE_SCOPE Bindings to GLOBAL_SCOPE
+         ctxt.setBindings(ctxt.getBindings(ScriptContext.ENGINE_SCOPE), ScriptContext.GLOBAL_SCOPE);
+
+         // create a new Bindings and set as ENGINE_SCOPE
+         ctxt.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
+
+         // define new function that calls "func" now in GLOBAL_SCOPE
+         engine.eval("newfunc = function() { return func() }");
+
+         // call "newfunc" and check the return value
+         Object value = ((Invocable)engine).invokeFunction("newfunc");
+         assertTrue(((Number)value).intValue() == 42);
+    }
 }
diff --git a/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java b/test/src/jdk/nashorn/api/scripting/test/ScriptEngineSecurityTest.java
similarity index 98%
rename from test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java
rename to test/src/jdk/nashorn/api/scripting/test/ScriptEngineSecurityTest.java
index 06b89e8..dfebd44 100644
--- a/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java
+++ b/test/src/jdk/nashorn/api/scripting/test/ScriptEngineSecurityTest.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+package jdk.nashorn.api.scripting.test;
 
 import static org.testng.Assert.fail;
 import java.lang.reflect.InvocationHandler;
@@ -32,6 +32,8 @@
 import javax.script.ScriptEngine;
 import javax.script.ScriptEngineManager;
 import javax.script.ScriptException;
+import jdk.nashorn.api.scripting.ClassFilter;
+import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
 import org.testng.annotations.Test;
 
 /**
diff --git a/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java b/test/src/jdk/nashorn/api/scripting/test/ScriptEngineTest.java
similarity index 84%
rename from test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
rename to test/src/jdk/nashorn/api/scripting/test/ScriptEngineTest.java
index ef4996f..3b683e2 100644
--- a/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
+++ b/test/src/jdk/nashorn/api/scripting/test/ScriptEngineTest.java
@@ -23,10 +23,11 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+package jdk.nashorn.api.scripting.test;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 
@@ -35,10 +36,12 @@
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
+import java.util.Collections;
 import java.util.concurrent.Callable;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Consumer;
 import java.util.function.Function;
+import javax.script.Bindings;
 import javax.script.Compilable;
 import javax.script.CompiledScript;
 import javax.script.Invocable;
@@ -48,14 +51,15 @@
 import javax.script.ScriptEngineManager;
 import javax.script.ScriptException;
 import javax.script.SimpleScriptContext;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import org.testng.annotations.Test;
 
 /**
  * Tests for JSR-223 script engine for Nashorn.
  *
  * @test
- * @build jdk.nashorn.api.scripting.Window jdk.nashorn.api.scripting.WindowEventHandler jdk.nashorn.api.scripting.VariableArityTestInterface jdk.nashorn.api.scripting.ScriptEngineTest
- * @run testng/othervm jdk.nashorn.api.scripting.ScriptEngineTest
+ * @build jdk.nashorn.api.scripting.test.Window jdk.nashorn.api.scripting.test.WindowEventHandler jdk.nashorn.api.scripting.test.VariableArityTestInterface jdk.nashorn.api.scripting.test.ScriptEngineTest
+ * @run testng/othervm jdk.nashorn.api.scripting.test.ScriptEngineTest
  */
 @SuppressWarnings("javadoc")
 public class ScriptEngineTest {
@@ -538,7 +542,7 @@
         final ScriptEngineManager m = new ScriptEngineManager();
         final ScriptEngine e = m.getEngineByName("nashorn");
         e.eval("obj = { foo: 'hello' }");
-        e.put("Window", e.eval("Packages.jdk.nashorn.api.scripting.Window"));
+        e.put("Window", e.eval("Packages.jdk.nashorn.api.scripting.test.Window"));
         assertEquals(e.eval("Window.funcJSObject(obj)"), "hello");
         assertEquals(e.eval("Window.funcScriptObjectMirror(obj)"), "hello");
         assertEquals(e.eval("Window.funcMap(obj)"), "hello");
@@ -672,6 +676,17 @@
         assertEquals("helloworld", inv.invokeMethod(ctx.get(), "join", ""));
     }
 
+    // @bug 8068524: NashornScriptEngineFactory.getParameter() throws IAE
+    // for an unknown key, doesn't conform to the general spec
+    @Test
+    public void getParameterInvalidKeyTest() throws Exception {
+        final ScriptEngineManager manager = new ScriptEngineManager();
+        final ScriptEngine e = manager.getEngineByName("nashorn");
+        // no exception expected here!
+        Object value = e.getFactory().getParameter("no value assigned to this key");
+        assertNull(value);
+    }
+
     // @bug JDK-8068889: ConsString arguments to a functional interface wasn't converted to string.
     @Test
     public void functionalInterfaceStringTest() throws Exception {
@@ -707,6 +722,148 @@
         assertTrue(invoked.get());
     }
 
+    @Test
+    public void testLengthOnArrayLikeObjects() throws Exception {
+        final ScriptEngine e = new ScriptEngineManager().getEngineByName("nashorn");
+        final Object val = e.eval("var arr = { length: 1, 0: 1}; arr.length");
+
+        assertTrue(Number.class.isAssignableFrom(val.getClass()));
+        assertTrue(((Number)val).intValue() == 1);
+    }
+
+    // @bug JDK-8068603: NashornScriptEngine.put/get() impls don't conform to NPE, IAE spec assertions
+    @Test
+    public void illegalBindingsValuesTest() throws Exception {
+        final ScriptEngineManager manager = new ScriptEngineManager();
+        final ScriptEngine e = manager.getEngineByName("nashorn");
+
+        try {
+            e.put(null, "null-value");
+            fail();
+        } catch (NullPointerException x) {
+            // expected
+        }
+
+        try {
+            e.put("", "empty-value");
+            fail();
+        } catch (IllegalArgumentException x) {
+            // expected
+        }
+
+        final Bindings b = e.getBindings(ScriptContext.ENGINE_SCOPE);
+        assertTrue(b instanceof ScriptObjectMirror);
+
+        try {
+            b.put(null, "null-value");
+            fail();
+        } catch (NullPointerException x) {
+            // expected
+        }
+
+        try {
+            b.put("", "empty-value");
+            fail();
+        } catch (IllegalArgumentException x) {
+            // expected
+        }
+
+        try {
+            b.get(null);
+            fail();
+        } catch (NullPointerException x) {
+            // expected
+        }
+
+        try {
+            b.get("");
+            fail();
+        } catch (IllegalArgumentException x) {
+            // expected
+        }
+
+        try {
+            b.get(1);
+            fail();
+        } catch (ClassCastException x) {
+            // expected
+        }
+
+        try {
+            b.remove(null);
+            fail();
+        } catch (NullPointerException x) {
+            // expected
+        }
+
+        try {
+            b.remove("");
+            fail();
+        } catch (IllegalArgumentException x) {
+            // expected
+        }
+
+        try {
+            b.remove(1);
+            fail();
+        } catch (ClassCastException x) {
+            // expected
+        }
+
+        try {
+            b.containsKey(null);
+            fail();
+        } catch (NullPointerException x) {
+            // expected
+        }
+
+        try {
+            b.containsKey("");
+            fail();
+        } catch (IllegalArgumentException x) {
+            // expected
+        }
+
+        try {
+            b.containsKey(1);
+            fail();
+        } catch (ClassCastException x) {
+            // expected
+        }
+
+        try {
+            b.putAll(null);
+            fail();
+        } catch (NullPointerException x) {
+            // expected
+        }
+
+        try {
+            b.putAll(Collections.singletonMap((String)null, "null-value"));
+            fail();
+        } catch (NullPointerException x) {
+            // expected
+        }
+
+        try {
+            b.putAll(Collections.singletonMap("", "empty-value"));
+            fail();
+        } catch (IllegalArgumentException x) {
+            // expected
+        }
+    }
+
+    // @bug 8071989: NashornScriptEngine returns javax.script.ScriptContext instance
+    // with insonsistent get/remove methods behavior for undefined attributes
+    @Test
+    public void testScriptContextGetRemoveUndefined() throws Exception {
+        final ScriptEngineManager manager = new ScriptEngineManager();
+        final ScriptEngine e = manager.getEngineByName("nashorn");
+        final ScriptContext ctx = e.getContext();
+        assertNull(ctx.getAttribute("undefinedname", ScriptContext.ENGINE_SCOPE));
+        assertNull(ctx.removeAttribute("undefinedname", ScriptContext.ENGINE_SCOPE));
+    }
+
     private static void checkProperty(final ScriptEngine e, final String name)
         throws ScriptException {
         final String value = System.getProperty(name);
diff --git a/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java b/test/src/jdk/nashorn/api/scripting/test/ScriptObjectMirrorTest.java
similarity index 98%
rename from test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java
rename to test/src/jdk/nashorn/api/scripting/test/ScriptObjectMirrorTest.java
index ce3b421..f9c78fc 100644
--- a/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java
+++ b/test/src/jdk/nashorn/api/scripting/test/ScriptObjectMirrorTest.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+package jdk.nashorn.api.scripting.test;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
@@ -41,6 +41,8 @@
 import javax.script.ScriptEngine;
 import javax.script.ScriptEngineManager;
 import javax.script.ScriptException;
+import jdk.nashorn.api.scripting.JSObject;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import org.testng.annotations.Test;
 
 /**
diff --git a/test/src/jdk/nashorn/api/scripting/VariableArityTestInterface.java b/test/src/jdk/nashorn/api/scripting/test/VariableArityTestInterface.java
similarity index 96%
rename from test/src/jdk/nashorn/api/scripting/VariableArityTestInterface.java
rename to test/src/jdk/nashorn/api/scripting/test/VariableArityTestInterface.java
index 8ce5e49..7761a3d 100644
--- a/test/src/jdk/nashorn/api/scripting/VariableArityTestInterface.java
+++ b/test/src/jdk/nashorn/api/scripting/test/VariableArityTestInterface.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+package jdk.nashorn.api.scripting.test;
 
 @SuppressWarnings("javadoc")
 public interface VariableArityTestInterface {
diff --git a/test/src/jdk/nashorn/api/scripting/Window.java b/test/src/jdk/nashorn/api/scripting/test/Window.java
similarity index 94%
rename from test/src/jdk/nashorn/api/scripting/Window.java
rename to test/src/jdk/nashorn/api/scripting/test/Window.java
index 7a7476f..6c60b16 100644
--- a/test/src/jdk/nashorn/api/scripting/Window.java
+++ b/test/src/jdk/nashorn/api/scripting/test/Window.java
@@ -23,10 +23,12 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+package jdk.nashorn.api.scripting.test;
 
 import java.util.Map;
 import javax.script.Bindings;
+import jdk.nashorn.api.scripting.JSObject;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
 
 @SuppressWarnings("javadoc")
 public class Window {
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/src/jdk/nashorn/api/scripting/test/WindowEventHandler.java
similarity index 96%
rename from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
rename to test/src/jdk/nashorn/api/scripting/test/WindowEventHandler.java
index dfcad5a..ddc879c 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/src/jdk/nashorn/api/scripting/test/WindowEventHandler.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+package jdk.nashorn.api.scripting.test;
 
 @SuppressWarnings("javadoc")
 public interface WindowEventHandler {
diff --git a/test/src/jdk/nashorn/api/scripting/resources/func.js b/test/src/jdk/nashorn/api/scripting/test/resources/func.js
similarity index 100%
rename from test/src/jdk/nashorn/api/scripting/resources/func.js
rename to test/src/jdk/nashorn/api/scripting/test/resources/func.js
diff --git a/test/src/jdk/nashorn/api/scripting/resources/gettersetter.js b/test/src/jdk/nashorn/api/scripting/test/resources/gettersetter.js
similarity index 100%
rename from test/src/jdk/nashorn/api/scripting/resources/gettersetter.js
rename to test/src/jdk/nashorn/api/scripting/test/resources/gettersetter.js
diff --git a/test/src/jdk/nashorn/api/scripting/resources/witheval.js b/test/src/jdk/nashorn/api/scripting/test/resources/witheval.js
similarity index 100%
rename from test/src/jdk/nashorn/api/scripting/resources/witheval.js
rename to test/src/jdk/nashorn/api/scripting/test/resources/witheval.js
diff --git a/test/src/jdk/nashorn/api/NashornSQLDriver.java b/test/src/jdk/nashorn/api/test/NashornSQLDriver.java
similarity index 98%
rename from test/src/jdk/nashorn/api/NashornSQLDriver.java
rename to test/src/jdk/nashorn/api/test/NashornSQLDriver.java
index dd62409..d1a5377 100644
--- a/test/src/jdk/nashorn/api/NashornSQLDriver.java
+++ b/test/src/jdk/nashorn/api/test/NashornSQLDriver.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.api;
+package jdk.nashorn.api.test;
 
 import java.sql.Connection;
 import java.sql.Driver;
diff --git a/test/src/jdk/nashorn/internal/codegen/CompilerTest.java b/test/src/jdk/nashorn/internal/codegen/test/CompilerTest.java
similarity index 99%
rename from test/src/jdk/nashorn/internal/codegen/CompilerTest.java
rename to test/src/jdk/nashorn/internal/codegen/test/CompilerTest.java
index 61d896b..5f99a39 100644
--- a/test/src/jdk/nashorn/internal/codegen/CompilerTest.java
+++ b/test/src/jdk/nashorn/internal/codegen/test/CompilerTest.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.internal.codegen;
+package jdk.nashorn.internal.codegen.test;
 
 import static jdk.nashorn.internal.runtime.Source.readFully;
 import static jdk.nashorn.internal.runtime.Source.sourceFor;
diff --git a/test/src/jdk/nashorn/internal/parser/ParserTest.java b/test/src/jdk/nashorn/internal/parser/test/ParserTest.java
similarity index 98%
rename from test/src/jdk/nashorn/internal/parser/ParserTest.java
rename to test/src/jdk/nashorn/internal/parser/test/ParserTest.java
index 110f623..7ba37fc 100644
--- a/test/src/jdk/nashorn/internal/parser/ParserTest.java
+++ b/test/src/jdk/nashorn/internal/parser/test/ParserTest.java
@@ -23,11 +23,12 @@
  * questions.
  */
 
-package jdk.nashorn.internal.parser;
+package jdk.nashorn.internal.parser.test;
 
 import static jdk.nashorn.internal.runtime.Source.readFully;
 import static jdk.nashorn.internal.runtime.Source.sourceFor;
 import java.io.File;
+import jdk.nashorn.internal.parser.Parser;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ErrorManager;
 import jdk.nashorn.internal.runtime.Source;
diff --git a/test/src/jdk/nashorn/internal/runtime/regexp/joni/JoniTest.java b/test/src/jdk/nashorn/internal/runtime/regexp/joni/test/JoniTest.java
similarity index 91%
rename from test/src/jdk/nashorn/internal/runtime/regexp/joni/JoniTest.java
rename to test/src/jdk/nashorn/internal/runtime/regexp/joni/test/JoniTest.java
index 616f769..a907f8f 100644
--- a/test/src/jdk/nashorn/internal/runtime/regexp/joni/JoniTest.java
+++ b/test/src/jdk/nashorn/internal/runtime/regexp/joni/test/JoniTest.java
@@ -23,15 +23,16 @@
  * questions.
  */
 
-package jdk.nashorn.internal.runtime.regexp.joni;
+package jdk.nashorn.internal.runtime.regexp.joni.test;
 
+import jdk.nashorn.internal.runtime.regexp.joni.Regex;
 import org.testng.annotations.Test;
 
 /**
  * Joni coverage tests
  *
  * @test
- * @run testng jdk.nashorn.internal.runtime.regexp.joni.JoniTest
+ * @run testng jdk.nashorn.internal.runtime.regexp.joni.test.JoniTest
  */
 @SuppressWarnings("javadoc")
 public class JoniTest {
diff --git a/test/src/jdk/nashorn/internal/runtime/regexp/JdkRegExpTest.java b/test/src/jdk/nashorn/internal/runtime/regexp/test/JdkRegExpTest.java
similarity index 88%
rename from test/src/jdk/nashorn/internal/runtime/regexp/JdkRegExpTest.java
rename to test/src/jdk/nashorn/internal/runtime/regexp/test/JdkRegExpTest.java
index 8156b78..20cb367 100644
--- a/test/src/jdk/nashorn/internal/runtime/regexp/JdkRegExpTest.java
+++ b/test/src/jdk/nashorn/internal/runtime/regexp/test/JdkRegExpTest.java
@@ -23,8 +23,11 @@
  * questions.
  */
 
-package jdk.nashorn.internal.runtime.regexp;
+package jdk.nashorn.internal.runtime.regexp.test;
 
+import jdk.nashorn.internal.runtime.regexp.RegExp;
+import jdk.nashorn.internal.runtime.regexp.RegExpFactory;
+import jdk.nashorn.internal.runtime.regexp.RegExpMatcher;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
@@ -35,7 +38,7 @@
  * Basic tests for the JDK based RegExp implementation.
  *
  * @test
- * @run testng jdk.nashorn.internal.runtime.regexp.JdkRegExpTest
+ * @run testng jdk.nashorn.internal.runtime.regexp.test.JdkRegExpTest
  */
 public class JdkRegExpTest {
 
diff --git a/test/src/jdk/nashorn/internal/runtime/test/AddAndRemoveOnListAdapterOutsideOfJavaScriptContextTest.java b/test/src/jdk/nashorn/internal/runtime/test/AddAndRemoveOnListAdapterOutsideOfJavaScriptContextTest.java
new file mode 100644
index 0000000..3115e18
--- /dev/null
+++ b/test/src/jdk/nashorn/internal/runtime/test/AddAndRemoveOnListAdapterOutsideOfJavaScriptContextTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.test;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.Deque;
+import java.util.List;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import org.testng.annotations.Test;
+
+/**
+ * @bug 8081204
+ * @summary adding and removing elements to a ListAdapter outside of JS context should work.
+ */
+@SuppressWarnings("javadoc")
+public class AddAndRemoveOnListAdapterOutsideOfJavaScriptContextTest {
+
+    @SuppressWarnings("unchecked")
+    private static <T> T getListAdapter() throws ScriptException {
+        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
+        return (T)engine.eval("Java.to([1, 2, 3, 4], 'java.util.List')");
+    }
+
+    @Test
+    public void testInvokePush() throws ScriptException {
+        final Deque<Object> l = getListAdapter();
+        l.addLast(5);
+        assertEquals(l.size(), 5);
+        assertEquals(l.getLast(), 5);
+        assertEquals(l.getFirst(), 1);
+    }
+
+    @Test
+    public void testPop() throws ScriptException {
+        final Deque<Object> l = getListAdapter();
+        assertEquals(l.removeLast(), 4);
+        assertEquals(l.size(), 3);
+        assertEquals(l.getLast(), 3);
+    }
+
+    @Test
+    public void testUnshift() throws ScriptException {
+        final Deque<Object> l = getListAdapter();
+        l.addFirst(0);
+        assertEquals(l.getFirst(), 0);
+        assertEquals(l.getLast(), 4);
+        assertEquals(l.size(), 5);
+    }
+
+    @Test
+    public void testShift() throws ScriptException {
+        final Deque<Object> l = getListAdapter();
+        l.removeFirst();
+        assertEquals(l.getFirst(), 2);
+        assertEquals(l.getLast(), 4);
+        assertEquals(l.size(), 3);
+    }
+
+    @Test
+    public void testSpliceAdd() throws ScriptException {
+        final List<Object> l = getListAdapter();
+        assertEquals(l, Arrays.asList(1, 2, 3, 4));
+        l.add(2, "foo");
+        assertEquals(l, Arrays.asList(1, 2, "foo", 3, 4));
+    }
+
+
+    @Test
+    public void testSpliceRemove() throws ScriptException {
+        final List<Object> l = getListAdapter();
+        assertEquals(l, Arrays.asList(1, 2, 3, 4));
+        l.remove(2);
+        assertEquals(l, Arrays.asList(1, 2, 4));
+    }
+}
diff --git a/test/src/jdk/nashorn/internal/runtime/ClassFilterTest.java b/test/src/jdk/nashorn/internal/runtime/test/ClassFilterTest.java
similarity index 99%
rename from test/src/jdk/nashorn/internal/runtime/ClassFilterTest.java
rename to test/src/jdk/nashorn/internal/runtime/test/ClassFilterTest.java
index 5c69141..7f53540 100644
--- a/test/src/jdk/nashorn/internal/runtime/ClassFilterTest.java
+++ b/test/src/jdk/nashorn/internal/runtime/test/ClassFilterTest.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.internal.runtime;
+package jdk.nashorn.internal.runtime.test;
 
 import static org.testng.Assert.fail;
 import java.io.File;
diff --git a/test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java b/test/src/jdk/nashorn/internal/runtime/test/CodeStoreAndPathTest.java
similarity index 97%
rename from test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java
rename to test/src/jdk/nashorn/internal/runtime/test/CodeStoreAndPathTest.java
index 2ca4820..46f57fd 100644
--- a/test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java
+++ b/test/src/jdk/nashorn/internal/runtime/test/CodeStoreAndPathTest.java
@@ -22,7 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package jdk.nashorn.internal.runtime;
+package jdk.nashorn.internal.runtime.test;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
@@ -38,10 +38,11 @@
 import org.testng.annotations.Test;
 
 /**
+ * @ignore Fails with jtreg, but passes with ant test run. Ignore for now.
  * @test
  * @bug 8039185 8039403
  * @summary  Test for persistent code cache and path handling
- * @run testng jdk.nashorn.internal.runtime.CodeStoreAndPathTest
+ * @run testng jdk.nashorn.internal.runtime.test.CodeStoreAndPathTest
  */
 @SuppressWarnings("javadoc")
 public class CodeStoreAndPathTest {
@@ -161,7 +162,7 @@
         e.eval(code3);// less than minimum size for storing
         // adding code1 and code2.
         final DirectoryStream<Path> stream = Files.newDirectoryStream(codeCachePath);
-        checkCompiledScripts(stream, 2);
+        checkCompiledScripts(stream, 4);
     }
 
     private static Path getCodeCachePath(final boolean optimistic) {
diff --git a/test/src/jdk/nashorn/internal/runtime/ConsStringTest.java b/test/src/jdk/nashorn/internal/runtime/test/ConsStringTest.java
similarity index 96%
rename from test/src/jdk/nashorn/internal/runtime/ConsStringTest.java
rename to test/src/jdk/nashorn/internal/runtime/test/ConsStringTest.java
index 16c3606..f86c5b7 100644
--- a/test/src/jdk/nashorn/internal/runtime/ConsStringTest.java
+++ b/test/src/jdk/nashorn/internal/runtime/test/ConsStringTest.java
@@ -23,8 +23,9 @@
  * questions.
  */
 
-package jdk.nashorn.internal.runtime;
+package jdk.nashorn.internal.runtime.test;
 
+import jdk.nashorn.internal.runtime.ConsString;
 import static org.testng.Assert.assertEquals;
 
 import org.testng.annotations.Test;
@@ -33,7 +34,7 @@
  * Tests for JSType methods.
  *
  * @test
- * @run testng jdk.nashorn.internal.runtime.ConsStringTest
+ * @run testng jdk.nashorn.internal.runtime.test.ConsStringTest
  */
 public class ConsStringTest {
 
diff --git a/test/src/jdk/nashorn/internal/runtime/ContextTest.java b/test/src/jdk/nashorn/internal/runtime/test/ContextTest.java
similarity index 92%
rename from test/src/jdk/nashorn/internal/runtime/ContextTest.java
rename to test/src/jdk/nashorn/internal/runtime/test/ContextTest.java
index 6770d7e..b927de2 100644
--- a/test/src/jdk/nashorn/internal/runtime/ContextTest.java
+++ b/test/src/jdk/nashorn/internal/runtime/test/ContextTest.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.internal.runtime;
+package jdk.nashorn.internal.runtime.test;
 
 import static jdk.nashorn.internal.runtime.Source.sourceFor;
 import static org.testng.Assert.assertEquals;
@@ -31,6 +31,12 @@
 import static org.testng.Assert.fail;
 import java.util.Map;
 import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.ErrorManager;
+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.options.Options;
 import org.testng.annotations.Test;
 
@@ -38,7 +44,7 @@
  * Basic Context API tests.
  *
  * @test
- * @run testng jdk.nashorn.internal.runtime.ContextTest
+ * @run testng jdk.nashorn.internal.runtime.test.ContextTest
  */
 @SuppressWarnings("javadoc")
 public class ContextTest {
diff --git a/test/src/jdk/nashorn/internal/runtime/ExceptionsNotSerializable.java b/test/src/jdk/nashorn/internal/runtime/test/ExceptionsNotSerializable.java
similarity index 92%
rename from test/src/jdk/nashorn/internal/runtime/ExceptionsNotSerializable.java
rename to test/src/jdk/nashorn/internal/runtime/test/ExceptionsNotSerializable.java
index 3b6d91b..3cb27ad 100644
--- a/test/src/jdk/nashorn/internal/runtime/ExceptionsNotSerializable.java
+++ b/test/src/jdk/nashorn/internal/runtime/test/ExceptionsNotSerializable.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.internal.runtime;
+package jdk.nashorn.internal.runtime.test;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.fail;
@@ -34,13 +34,15 @@
 import javax.script.ScriptEngine;
 import javax.script.ScriptException;
 import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import jdk.nashorn.internal.runtime.RewriteException;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
 import org.testng.annotations.Test;
 
 /**
  * JDK-8044518: Ensure exceptions related to optimistic recompilation are not serializable
  *
  * @test
- * @run testng jdk.nashorn.internal.runtime.ExceptionsNotSerializable
+ * @run testng jdk.nashorn.internal.runtime.test.ExceptionsNotSerializable
  */
 @SuppressWarnings("javadoc")
 public class ExceptionsNotSerializable {
diff --git a/test/src/jdk/nashorn/internal/runtime/test/JDK_8078414_Test.java b/test/src/jdk/nashorn/internal/runtime/test/JDK_8078414_Test.java
new file mode 100644
index 0000000..a1ccfb6
--- /dev/null
+++ b/test/src/jdk/nashorn/internal/runtime/test/JDK_8078414_Test.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.test;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+import javax.script.Bindings;
+import jdk.nashorn.api.scripting.JSObject;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
+import jdk.nashorn.internal.objects.NativeArray;
+import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.linker.Bootstrap;
+import org.testng.annotations.Test;
+
+/**
+ * @test
+ * @bug 8078414
+ * @summary Test that arbitrary classes can't be converted to mirror's superclasses/interfaces.
+ * @run testng jdk.nashorn.internal.runtime.test.JDK_8078414_Test
+ */
+public class JDK_8078414_Test {
+    @Test
+    public void testCanNotConvertArbitraryClassToMirror() {
+        assertCanNotConvert(Double.class, Map.class);
+        assertCanNotConvert(Double.class, Bindings.class);
+        assertCanNotConvert(Double.class, JSObject.class);
+        assertCanNotConvert(Double.class, ScriptObjectMirror.class);
+    }
+
+    @Test
+    public void testCanConvertObjectToMirror() {
+        assertCanConvertToMirror(Object.class);
+    }
+
+    @Test
+    public void testCanConvertScriptObjectToMirror() {
+        assertCanConvertToMirror(ScriptObject.class);
+    }
+
+    @Test
+    public void testCanConvertScriptObjectSubclassToMirror() {
+        assertCanConvertToMirror(NativeArray.class);
+    }
+
+    @Test
+    public void testCanConvertArbitraryInterfaceToMirror() {
+        // We allow arbitrary interface classes, depending on what implements them, to end up being
+        // convertible to ScriptObjectMirror, as an implementation can theoretically pass an
+        // "instanceof ScriptObject" guard.
+        assertCanConvertToMirror(TestInterface.class);
+    }
+
+    public static interface TestInterface {
+    }
+
+    private static boolean canConvert(final Class<?> from, final Class<?> to) {
+        return Bootstrap.getLinkerServices().canConvert(from, to);
+    }
+
+    private static void assertCanConvert(final Class<?> from, final Class<?> to) {
+        assertTrue(canConvert(from, to));
+    }
+
+    private static void assertCanNotConvert(final Class<?> from, final Class<?> to) {
+        assertFalse(canConvert(from, to));
+    }
+
+    private static void assertCanConvertToMirror(final Class<?> from) {
+        assertCanConvert(from, Map.class);
+        assertCanConvert(from, Bindings.class);
+        assertCanConvert(from, JSObject.class);
+        assertCanConvert(from, ScriptObjectMirror.class);
+    }
+}
diff --git a/test/src/jdk/nashorn/internal/runtime/test/JDK_8081015_Test.java b/test/src/jdk/nashorn/internal/runtime/test/JDK_8081015_Test.java
new file mode 100644
index 0000000..6051591
--- /dev/null
+++ b/test/src/jdk/nashorn/internal/runtime/test/JDK_8081015_Test.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+
+import java.util.Collection;
+import java.util.Queue;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import jdk.nashorn.test.models.JDK_8081015_TestModel;
+import org.testng.annotations.Test;
+
+/**
+ * @bug 8081015
+ * @summary Test that native arrays get converted to {@link Queue} and {@link Collection}.
+ */
+@SuppressWarnings("javadoc")
+public class JDK_8081015_Test {
+    @Test
+    public void testConvertToCollection() throws ScriptException {
+        test("receiveCollection");
+    }
+
+    @Test
+    public void testConvertToDeque() throws ScriptException {
+        test("receiveDeque");
+    }
+
+    @Test
+    public void testConvertToList() throws ScriptException {
+        test("receiveList");
+    }
+
+    @Test
+    public void testConvertToQueue() throws ScriptException {
+        test("receiveQueue");
+    }
+
+    private static void test(final String methodName) throws ScriptException {
+        final ScriptEngine engine = new NashornScriptEngineFactory().getScriptEngine();
+        final JDK_8081015_TestModel model = new JDK_8081015_TestModel();
+        engine.put("test", model);
+
+        assertNull(model.getLastInvoked());
+        engine.eval("test." + methodName + "([1, 2, 3.3, 'foo'])");
+        assertEquals(model.getLastInvoked(), methodName );
+    }
+}
diff --git a/test/src/jdk/nashorn/internal/runtime/JSTypeTest.java b/test/src/jdk/nashorn/internal/runtime/test/JSTypeTest.java
similarity index 97%
rename from test/src/jdk/nashorn/internal/runtime/JSTypeTest.java
rename to test/src/jdk/nashorn/internal/runtime/test/JSTypeTest.java
index 406ce1c..a91a442 100644
--- a/test/src/jdk/nashorn/internal/runtime/JSTypeTest.java
+++ b/test/src/jdk/nashorn/internal/runtime/test/JSTypeTest.java
@@ -23,8 +23,10 @@
  * questions.
  */
 
-package jdk.nashorn.internal.runtime;
+package jdk.nashorn.internal.runtime.test;
 
+import jdk.nashorn.internal.runtime.JSType;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertTrue;
@@ -35,7 +37,7 @@
  * Tests for JSType methods.
  *
  * @test
- * @run testng jdk.nashorn.internal.runtime.JSTypeTest
+ * @run testng jdk.nashorn.internal.runtime.test.JSTypeTest
  */
 public class JSTypeTest {
     /**
diff --git a/test/src/jdk/nashorn/internal/runtime/LexicalBindingTest.java b/test/src/jdk/nashorn/internal/runtime/test/LexicalBindingTest.java
similarity index 98%
rename from test/src/jdk/nashorn/internal/runtime/LexicalBindingTest.java
rename to test/src/jdk/nashorn/internal/runtime/test/LexicalBindingTest.java
index 2cd0bf0..713a33c 100644
--- a/test/src/jdk/nashorn/internal/runtime/LexicalBindingTest.java
+++ b/test/src/jdk/nashorn/internal/runtime/test/LexicalBindingTest.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.internal.runtime;
+package jdk.nashorn.internal.runtime.test;
 
 import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
 import org.testng.annotations.Test;
@@ -40,7 +40,7 @@
  * Top-level lexical binding tests.
  *
  * @test
- * @run testng jdk.nashorn.internal.runtime.LexicalBindingTest
+ * @run testng jdk.nashorn.internal.runtime.test.LexicalBindingTest
  */
 @SuppressWarnings("javadoc")
 public class LexicalBindingTest {
diff --git a/test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java b/test/src/jdk/nashorn/internal/runtime/test/NoPersistenceCachingTest.java
similarity index 97%
rename from test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java
rename to test/src/jdk/nashorn/internal/runtime/test/NoPersistenceCachingTest.java
index 91f1960..d9643e6 100644
--- a/test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java
+++ b/test/src/jdk/nashorn/internal/runtime/test/NoPersistenceCachingTest.java
@@ -22,7 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package jdk.nashorn.internal.runtime;
+package jdk.nashorn.internal.runtime.test;
 
 import static org.testng.Assert.fail;
 import java.io.ByteArrayOutputStream;
@@ -43,7 +43,7 @@
  * @test
  * @bug 8037378
  * @summary Sanity tests for no persistence caching
- * @run testng/othervm jdk.nashorn.internal.runtime.NoPersistenceCachingTest
+ * @run testng/othervm jdk.nashorn.internal.runtime.test.NoPersistenceCachingTest
  */
 @SuppressWarnings("javadoc")
 public class NoPersistenceCachingTest {
diff --git a/test/src/jdk/nashorn/internal/runtime/SourceTest.java b/test/src/jdk/nashorn/internal/runtime/test/SourceTest.java
similarity index 96%
rename from test/src/jdk/nashorn/internal/runtime/SourceTest.java
rename to test/src/jdk/nashorn/internal/runtime/test/SourceTest.java
index 12645c0..fdf406c 100644
--- a/test/src/jdk/nashorn/internal/runtime/SourceTest.java
+++ b/test/src/jdk/nashorn/internal/runtime/test/SourceTest.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.internal.runtime;
+package jdk.nashorn.internal.runtime.test;
 
 import static jdk.nashorn.internal.runtime.Source.sourceFor;
 import static org.testng.Assert.assertEquals;
@@ -36,6 +36,7 @@
 import java.net.URL;
 import java.util.Arrays;
 import jdk.nashorn.api.scripting.URLReader;
+import jdk.nashorn.internal.runtime.Source;
 import org.testng.annotations.Test;
 
 /**
@@ -48,7 +49,7 @@
     final private static String SOURCE_STRING = "var x = 1;";
     final private static char[] SOURCE_CHARS = SOURCE_STRING.toCharArray();
     final private static String RESOURCE_PATH = "resources/load_test.js";
-    final private static File SOURCE_FILE = new File("build/test/classes/jdk/nashorn/internal/runtime/" + RESOURCE_PATH);
+    final private static File SOURCE_FILE = new File("build/test/classes/jdk/nashorn/internal/runtime/test/" + RESOURCE_PATH);
     final private static URL  SOURCE_URL = SourceTest.class.getResource(RESOURCE_PATH);
 
 
diff --git a/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java b/test/src/jdk/nashorn/internal/runtime/test/TrustedScriptEngineTest.java
similarity index 99%
rename from test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java
rename to test/src/jdk/nashorn/internal/runtime/test/TrustedScriptEngineTest.java
index 09c90dc..416a204 100644
--- a/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java
+++ b/test/src/jdk/nashorn/internal/runtime/test/TrustedScriptEngineTest.java
@@ -23,7 +23,7 @@
  * questions.
  */
 
-package jdk.nashorn.internal.runtime;
+package jdk.nashorn.internal.runtime.test;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
@@ -36,6 +36,7 @@
 import javax.script.SimpleScriptContext;
 import jdk.nashorn.api.scripting.ClassFilter;
 import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import jdk.nashorn.internal.runtime.Version;
 import org.testng.annotations.Test;
 
 /**
diff --git a/test/src/jdk/nashorn/internal/runtime/resources/load_test.js b/test/src/jdk/nashorn/internal/runtime/test/resources/load_test.js
similarity index 100%
rename from test/src/jdk/nashorn/internal/runtime/resources/load_test.js
rename to test/src/jdk/nashorn/internal/runtime/test/resources/load_test.js
diff --git a/test/src/jdk/nashorn/internal/test/framework/TestFinder.java b/test/src/jdk/nashorn/internal/test/framework/TestFinder.java
index 32b1cbd..bbfe38d 100644
--- a/test/src/jdk/nashorn/internal/test/framework/TestFinder.java
+++ b/test/src/jdk/nashorn/internal/test/framework/TestFinder.java
@@ -22,7 +22,6 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.nashorn.internal.test.framework;
 
 import static jdk.nashorn.internal.test.framework.TestConfig.OPTIONS_CHECK_COMPILE_MSG;
@@ -61,14 +60,15 @@
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Scanner;
 import java.util.Set;
 import javax.xml.xpath.XPath;
 import javax.xml.xpath.XPathConstants;
 import javax.xml.xpath.XPathExpressionException;
 import javax.xml.xpath.XPathFactory;
+import jdk.nashorn.internal.runtime.ScriptingFunctions;
 import org.w3c.dom.NodeList;
 import org.xml.sax.InputSource;
 
@@ -78,28 +78,33 @@
  */
 @SuppressWarnings("javadoc")
 public final class TestFinder {
-    private TestFinder() {}
 
-    interface TestFactory<T> {
-        // 'test' instance type is decided by the client.
-        T createTest(final String framework, final File testFile, final List<String> engineOptions, final Map<String, String> testOptions, final List<String> arguments);
-        // place to log messages from TestFinder
-        void log(String mg);
+    private TestFinder() {
     }
 
+    interface TestFactory<T> {
+
+        // 'test' instance type is decided by the client.
+
+        T createTest(final String framework, final File testFile, final List<String> engineOptions, final Map<String, String> testOptions, final List<String> arguments);
+
+        // place to log messages from TestFinder
+
+        void log(String mg);
+    }
 
     // finds all tests from configuration and calls TestFactory to create 'test' instance for each script test found
     static <T> void findAllTests(final List<T> tests, final Set<String> orphans, final TestFactory<T> testFactory) throws Exception {
         final String framework = System.getProperty(TEST_JS_FRAMEWORK);
         final String testList = System.getProperty(TEST_JS_LIST);
         final String failedTestFileName = System.getProperty(TEST_FAILED_LIST_FILE);
-        if(failedTestFileName != null) {
+        if (failedTestFileName != null) {
             final File failedTestFile = new File(failedTestFileName);
-            if(failedTestFile.exists() && failedTestFile.length() > 0L) {
-                try(final BufferedReader r = new BufferedReader(new FileReader(failedTestFile))) {
-                    for(;;) {
+            if (failedTestFile.exists() && failedTestFile.length() > 0L) {
+                try (final BufferedReader r = new BufferedReader(new FileReader(failedTestFile))) {
+                    for (;;) {
                         final String testFileName = r.readLine();
-                        if(testFileName == null) {
+                        if (testFileName == null) {
                             break;
                         }
                         handleOneTest(framework, new File(testFileName).toPath(), tests, orphans, testFactory);
@@ -151,7 +156,7 @@
         final Exception[] exceptions = new Exception[1];
         final List<String> excludedActualTests = new ArrayList<>();
 
-        if (! dir.toFile().isDirectory()) {
+        if (!dir.toFile().isDirectory()) {
             factory.log("WARNING: " + dir + " not found or not a directory");
         }
 
@@ -219,27 +224,28 @@
 
         boolean explicitOptimistic = false;
 
-        try (Scanner scanner = new Scanner(testFile)) {
-            while (scanner.hasNext()) {
-                // TODO: Scan for /ref=file qualifiers, etc, to determine run
-                // behavior
-                String token = scanner.next();
-                if (token.startsWith("/*")) {
-                    inComment = true;
-                } else if (token.endsWith(("*/"))) {
-                    inComment = false;
-                } else if (!inComment) {
-                    continue;
-                }
+        String allContent = new String(Files.readAllBytes(testFile));
+        Iterator<String> scanner = ScriptingFunctions.tokenizeString(allContent).iterator();
+        while (scanner.hasNext()) {
+            // TODO: Scan for /ref=file qualifiers, etc, to determine run
+            // behavior
+            String token = scanner.next();
+            if (token.startsWith("/*")) {
+                inComment = true;
+            } else if (token.endsWith(("*/"))) {
+                inComment = false;
+            } else if (!inComment) {
+                continue;
+            }
 
-                // remove whitespace and trailing semicolons, if any
-                // (trailing semicolons are found in some sputnik tests)
-                token = token.trim();
-                final int semicolon = token.indexOf(';');
-                if (semicolon > 0) {
-                    token = token.substring(0, semicolon);
-                }
-                switch (token) {
+            // remove whitespace and trailing semicolons, if any
+            // (trailing semicolons are found in some sputnik tests)
+            token = token.trim();
+            final int semicolon = token.indexOf(';');
+            if (semicolon > 0) {
+                token = token.substring(0, semicolon);
+            }
+            switch (token) {
                 case "@test":
                     isTest = true;
                     break;
@@ -308,24 +314,21 @@
                     break;
                 default:
                     break;
-                }
+            }
 
-                // negative tests are expected to fail at runtime only
-                // for those tests that are expected to fail at compile time,
-                // add @test/compile-error
-                if (token.equals("@negative") || token.equals("@strict_mode_negative")) {
-                    shouldRun = true;
-                    runFailure = true;
-                }
+            // negative tests are expected to fail at runtime only
+            // for those tests that are expected to fail at compile time,
+            // add @test/compile-error
+            if (token.equals("@negative") || token.equals("@strict_mode_negative")) {
+                shouldRun = true;
+                runFailure = true;
+            }
 
-                if (token.equals("@strict_mode") || token.equals("@strict_mode_negative") || token.equals("@onlyStrict") || token.equals("@noStrict")) {
-                    if (!strictModeEnabled()) {
-                        return;
-                    }
+            if (token.equals("@strict_mode") || token.equals("@strict_mode_negative") || token.equals("@onlyStrict") || token.equals("@noStrict")) {
+                if (!strictModeEnabled()) {
+                    return;
                 }
             }
-        } catch (final Exception ignored) {
-            return;
         }
 
         if (isTest) {
@@ -369,8 +372,8 @@
     private static final boolean OPTIMISTIC_OVERRIDE = true;
 
     /**
-     * Check if there is an optimistic override, that disables the default
-     * false optimistic types and sets them to true, for testing purposes
+     * Check if there is an optimistic override, that disables the default false
+     * optimistic types and sets them to true, for testing purposes
      *
      * @return true if optimistic type override has been set by test suite
      */
@@ -379,10 +382,9 @@
     }
 
     /**
-     * Add an optimistic-types=true option to an argument list if this
-     * is set to override the default false. Add an optimistic-types=true
-     * options to an argument list if this is set to override the default
-     * true
+     * Add an optimistic-types=true option to an argument list if this is set to
+     * override the default false. Add an optimistic-types=true options to an
+     * argument list if this is set to override the default true
      *
      * @args new argument list array
      */
@@ -396,8 +398,8 @@
     }
 
     /**
-     * Add an optimistic-types=true option to an argument list if this
-     * is set to override the default false
+     * Add an optimistic-types=true option to an argument list if this is set to
+     * override the default false
      *
      * @args argument list
      */
@@ -438,7 +440,7 @@
 
     private static void loadExcludesFile(final String testExcludesFile, final Set<String> testExcludeSet) throws XPathExpressionException {
         final XPath xpath = XPathFactory.newInstance().newXPath();
-        final NodeList testIds = (NodeList)xpath.evaluate("/excludeList/test/@id", new InputSource(testExcludesFile), XPathConstants.NODESET);
+        final NodeList testIds = (NodeList) xpath.evaluate("/excludeList/test/@id", new InputSource(testExcludesFile), XPathConstants.NODESET);
         for (int i = testIds.getLength() - 1; i >= 0; i--) {
             testExcludeSet.add(testIds.item(i).getNodeValue());
         }
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/src/jdk/nashorn/test/models/A.java
similarity index 83%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/src/jdk/nashorn/test/models/A.java
index dfcad5a..3b302a6 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/src/jdk/nashorn/test/models/A.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,9 +23,10 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+package jdk.nashorn.test.models;
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
+public interface A {
+    default String a() {
+        return "from A.a";
+    }
 }
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/src/jdk/nashorn/test/models/B.java
similarity index 83%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/src/jdk/nashorn/test/models/B.java
index dfcad5a..8c98c19 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/src/jdk/nashorn/test/models/B.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,9 +23,10 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+package jdk.nashorn.test.models;
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
+public interface B extends A {
+    default String b() {
+        return "from B.b";
+    }
 }
diff --git a/test/src/jdk/nashorn/test/models/BigAbstract.java b/test/src/jdk/nashorn/test/models/BigAbstract.java
new file mode 100644
index 0000000..2075eeb
--- /dev/null
+++ b/test/src/jdk/nashorn/test/models/BigAbstract.java
@@ -0,0 +1,4709 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.models;
+
+public abstract class BigAbstract {
+    public static void accept(BigAbstract ba) {
+    }
+
+    public abstract void f0();
+    public abstract void f1();
+    public abstract void f2();
+    public abstract void f3();
+    public abstract void f4();
+    public abstract void f5();
+    public abstract void f6();
+    public abstract void f7();
+    public abstract void f8();
+    public abstract void f9();
+    public abstract void f10();
+    public abstract void f11();
+    public abstract void f12();
+    public abstract void f13();
+    public abstract void f14();
+    public abstract void f15();
+    public abstract void f16();
+    public abstract void f17();
+    public abstract void f18();
+    public abstract void f19();
+    public abstract void f20();
+    public abstract void f21();
+    public abstract void f22();
+    public abstract void f23();
+    public abstract void f24();
+    public abstract void f25();
+    public abstract void f26();
+    public abstract void f27();
+    public abstract void f28();
+    public abstract void f29();
+    public abstract void f30();
+    public abstract void f31();
+    public abstract void f32();
+    public abstract void f33();
+    public abstract void f34();
+    public abstract void f35();
+    public abstract void f36();
+    public abstract void f37();
+    public abstract void f38();
+    public abstract void f39();
+    public abstract void f40();
+    public abstract void f41();
+    public abstract void f42();
+    public abstract void f43();
+    public abstract void f44();
+    public abstract void f45();
+    public abstract void f46();
+    public abstract void f47();
+    public abstract void f48();
+    public abstract void f49();
+    public abstract void f50();
+    public abstract void f51();
+    public abstract void f52();
+    public abstract void f53();
+    public abstract void f54();
+    public abstract void f55();
+    public abstract void f56();
+    public abstract void f57();
+    public abstract void f58();
+    public abstract void f59();
+    public abstract void f60();
+    public abstract void f61();
+    public abstract void f62();
+    public abstract void f63();
+    public abstract void f64();
+    public abstract void f65();
+    public abstract void f66();
+    public abstract void f67();
+    public abstract void f68();
+    public abstract void f69();
+    public abstract void f70();
+    public abstract void f71();
+    public abstract void f72();
+    public abstract void f73();
+    public abstract void f74();
+    public abstract void f75();
+    public abstract void f76();
+    public abstract void f77();
+    public abstract void f78();
+    public abstract void f79();
+    public abstract void f80();
+    public abstract void f81();
+    public abstract void f82();
+    public abstract void f83();
+    public abstract void f84();
+    public abstract void f85();
+    public abstract void f86();
+    public abstract void f87();
+    public abstract void f88();
+    public abstract void f89();
+    public abstract void f90();
+    public abstract void f91();
+    public abstract void f92();
+    public abstract void f93();
+    public abstract void f94();
+    public abstract void f95();
+    public abstract void f96();
+    public abstract void f97();
+    public abstract void f98();
+    public abstract void f99();
+    public abstract void f100();
+    public abstract void f101();
+    public abstract void f102();
+    public abstract void f103();
+    public abstract void f104();
+    public abstract void f105();
+    public abstract void f106();
+    public abstract void f107();
+    public abstract void f108();
+    public abstract void f109();
+    public abstract void f110();
+    public abstract void f111();
+    public abstract void f112();
+    public abstract void f113();
+    public abstract void f114();
+    public abstract void f115();
+    public abstract void f116();
+    public abstract void f117();
+    public abstract void f118();
+    public abstract void f119();
+    public abstract void f120();
+    public abstract void f121();
+    public abstract void f122();
+    public abstract void f123();
+    public abstract void f124();
+    public abstract void f125();
+    public abstract void f126();
+    public abstract void f127();
+    public abstract void f128();
+    public abstract void f129();
+    public abstract void f130();
+    public abstract void f131();
+    public abstract void f132();
+    public abstract void f133();
+    public abstract void f134();
+    public abstract void f135();
+    public abstract void f136();
+    public abstract void f137();
+    public abstract void f138();
+    public abstract void f139();
+    public abstract void f140();
+    public abstract void f141();
+    public abstract void f142();
+    public abstract void f143();
+    public abstract void f144();
+    public abstract void f145();
+    public abstract void f146();
+    public abstract void f147();
+    public abstract void f148();
+    public abstract void f149();
+    public abstract void f150();
+    public abstract void f151();
+    public abstract void f152();
+    public abstract void f153();
+    public abstract void f154();
+    public abstract void f155();
+    public abstract void f156();
+    public abstract void f157();
+    public abstract void f158();
+    public abstract void f159();
+    public abstract void f160();
+    public abstract void f161();
+    public abstract void f162();
+    public abstract void f163();
+    public abstract void f164();
+    public abstract void f165();
+    public abstract void f166();
+    public abstract void f167();
+    public abstract void f168();
+    public abstract void f169();
+    public abstract void f170();
+    public abstract void f171();
+    public abstract void f172();
+    public abstract void f173();
+    public abstract void f174();
+    public abstract void f175();
+    public abstract void f176();
+    public abstract void f177();
+    public abstract void f178();
+    public abstract void f179();
+    public abstract void f180();
+    public abstract void f181();
+    public abstract void f182();
+    public abstract void f183();
+    public abstract void f184();
+    public abstract void f185();
+    public abstract void f186();
+    public abstract void f187();
+    public abstract void f188();
+    public abstract void f189();
+    public abstract void f190();
+    public abstract void f191();
+    public abstract void f192();
+    public abstract void f193();
+    public abstract void f194();
+    public abstract void f195();
+    public abstract void f196();
+    public abstract void f197();
+    public abstract void f198();
+    public abstract void f199();
+    public abstract void f200();
+    public abstract void f201();
+    public abstract void f202();
+    public abstract void f203();
+    public abstract void f204();
+    public abstract void f205();
+    public abstract void f206();
+    public abstract void f207();
+    public abstract void f208();
+    public abstract void f209();
+    public abstract void f210();
+    public abstract void f211();
+    public abstract void f212();
+    public abstract void f213();
+    public abstract void f214();
+    public abstract void f215();
+    public abstract void f216();
+    public abstract void f217();
+    public abstract void f218();
+    public abstract void f219();
+    public abstract void f220();
+    public abstract void f221();
+    public abstract void f222();
+    public abstract void f223();
+    public abstract void f224();
+    public abstract void f225();
+    public abstract void f226();
+    public abstract void f227();
+    public abstract void f228();
+    public abstract void f229();
+    public abstract void f230();
+    public abstract void f231();
+    public abstract void f232();
+    public abstract void f233();
+    public abstract void f234();
+    public abstract void f235();
+    public abstract void f236();
+    public abstract void f237();
+    public abstract void f238();
+    public abstract void f239();
+    public abstract void f240();
+    public abstract void f241();
+    public abstract void f242();
+    public abstract void f243();
+    public abstract void f244();
+    public abstract void f245();
+    public abstract void f246();
+    public abstract void f247();
+    public abstract void f248();
+    public abstract void f249();
+    public abstract void f250();
+    public abstract void f251();
+    public abstract void f252();
+    public abstract void f253();
+    public abstract void f254();
+    public abstract void f255();
+    public abstract void f256();
+    public abstract void f257();
+    public abstract void f258();
+    public abstract void f259();
+    public abstract void f260();
+    public abstract void f261();
+    public abstract void f262();
+    public abstract void f263();
+    public abstract void f264();
+    public abstract void f265();
+    public abstract void f266();
+    public abstract void f267();
+    public abstract void f268();
+    public abstract void f269();
+    public abstract void f270();
+    public abstract void f271();
+    public abstract void f272();
+    public abstract void f273();
+    public abstract void f274();
+    public abstract void f275();
+    public abstract void f276();
+    public abstract void f277();
+    public abstract void f278();
+    public abstract void f279();
+    public abstract void f280();
+    public abstract void f281();
+    public abstract void f282();
+    public abstract void f283();
+    public abstract void f284();
+    public abstract void f285();
+    public abstract void f286();
+    public abstract void f287();
+    public abstract void f288();
+    public abstract void f289();
+    public abstract void f290();
+    public abstract void f291();
+    public abstract void f292();
+    public abstract void f293();
+    public abstract void f294();
+    public abstract void f295();
+    public abstract void f296();
+    public abstract void f297();
+    public abstract void f298();
+    public abstract void f299();
+    public abstract void f300();
+    public abstract void f301();
+    public abstract void f302();
+    public abstract void f303();
+    public abstract void f304();
+    public abstract void f305();
+    public abstract void f306();
+    public abstract void f307();
+    public abstract void f308();
+    public abstract void f309();
+    public abstract void f310();
+    public abstract void f311();
+    public abstract void f312();
+    public abstract void f313();
+    public abstract void f314();
+    public abstract void f315();
+    public abstract void f316();
+    public abstract void f317();
+    public abstract void f318();
+    public abstract void f319();
+    public abstract void f320();
+    public abstract void f321();
+    public abstract void f322();
+    public abstract void f323();
+    public abstract void f324();
+    public abstract void f325();
+    public abstract void f326();
+    public abstract void f327();
+    public abstract void f328();
+    public abstract void f329();
+    public abstract void f330();
+    public abstract void f331();
+    public abstract void f332();
+    public abstract void f333();
+    public abstract void f334();
+    public abstract void f335();
+    public abstract void f336();
+    public abstract void f337();
+    public abstract void f338();
+    public abstract void f339();
+    public abstract void f340();
+    public abstract void f341();
+    public abstract void f342();
+    public abstract void f343();
+    public abstract void f344();
+    public abstract void f345();
+    public abstract void f346();
+    public abstract void f347();
+    public abstract void f348();
+    public abstract void f349();
+    public abstract void f350();
+    public abstract void f351();
+    public abstract void f352();
+    public abstract void f353();
+    public abstract void f354();
+    public abstract void f355();
+    public abstract void f356();
+    public abstract void f357();
+    public abstract void f358();
+    public abstract void f359();
+    public abstract void f360();
+    public abstract void f361();
+    public abstract void f362();
+    public abstract void f363();
+    public abstract void f364();
+    public abstract void f365();
+    public abstract void f366();
+    public abstract void f367();
+    public abstract void f368();
+    public abstract void f369();
+    public abstract void f370();
+    public abstract void f371();
+    public abstract void f372();
+    public abstract void f373();
+    public abstract void f374();
+    public abstract void f375();
+    public abstract void f376();
+    public abstract void f377();
+    public abstract void f378();
+    public abstract void f379();
+    public abstract void f380();
+    public abstract void f381();
+    public abstract void f382();
+    public abstract void f383();
+    public abstract void f384();
+    public abstract void f385();
+    public abstract void f386();
+    public abstract void f387();
+    public abstract void f388();
+    public abstract void f389();
+    public abstract void f390();
+    public abstract void f391();
+    public abstract void f392();
+    public abstract void f393();
+    public abstract void f394();
+    public abstract void f395();
+    public abstract void f396();
+    public abstract void f397();
+    public abstract void f398();
+    public abstract void f399();
+    public abstract void f400();
+    public abstract void f401();
+    public abstract void f402();
+    public abstract void f403();
+    public abstract void f404();
+    public abstract void f405();
+    public abstract void f406();
+    public abstract void f407();
+    public abstract void f408();
+    public abstract void f409();
+    public abstract void f410();
+    public abstract void f411();
+    public abstract void f412();
+    public abstract void f413();
+    public abstract void f414();
+    public abstract void f415();
+    public abstract void f416();
+    public abstract void f417();
+    public abstract void f418();
+    public abstract void f419();
+    public abstract void f420();
+    public abstract void f421();
+    public abstract void f422();
+    public abstract void f423();
+    public abstract void f424();
+    public abstract void f425();
+    public abstract void f426();
+    public abstract void f427();
+    public abstract void f428();
+    public abstract void f429();
+    public abstract void f430();
+    public abstract void f431();
+    public abstract void f432();
+    public abstract void f433();
+    public abstract void f434();
+    public abstract void f435();
+    public abstract void f436();
+    public abstract void f437();
+    public abstract void f438();
+    public abstract void f439();
+    public abstract void f440();
+    public abstract void f441();
+    public abstract void f442();
+    public abstract void f443();
+    public abstract void f444();
+    public abstract void f445();
+    public abstract void f446();
+    public abstract void f447();
+    public abstract void f448();
+    public abstract void f449();
+    public abstract void f450();
+    public abstract void f451();
+    public abstract void f452();
+    public abstract void f453();
+    public abstract void f454();
+    public abstract void f455();
+    public abstract void f456();
+    public abstract void f457();
+    public abstract void f458();
+    public abstract void f459();
+    public abstract void f460();
+    public abstract void f461();
+    public abstract void f462();
+    public abstract void f463();
+    public abstract void f464();
+    public abstract void f465();
+    public abstract void f466();
+    public abstract void f467();
+    public abstract void f468();
+    public abstract void f469();
+    public abstract void f470();
+    public abstract void f471();
+    public abstract void f472();
+    public abstract void f473();
+    public abstract void f474();
+    public abstract void f475();
+    public abstract void f476();
+    public abstract void f477();
+    public abstract void f478();
+    public abstract void f479();
+    public abstract void f480();
+    public abstract void f481();
+    public abstract void f482();
+    public abstract void f483();
+    public abstract void f484();
+    public abstract void f485();
+    public abstract void f486();
+    public abstract void f487();
+    public abstract void f488();
+    public abstract void f489();
+    public abstract void f490();
+    public abstract void f491();
+    public abstract void f492();
+    public abstract void f493();
+    public abstract void f494();
+    public abstract void f495();
+    public abstract void f496();
+    public abstract void f497();
+    public abstract void f498();
+    public abstract void f499();
+    public abstract void f500();
+    public abstract void f501();
+    public abstract void f502();
+    public abstract void f503();
+    public abstract void f504();
+    public abstract void f505();
+    public abstract void f506();
+    public abstract void f507();
+    public abstract void f508();
+    public abstract void f509();
+    public abstract void f510();
+    public abstract void f511();
+    public abstract void f512();
+    public abstract void f513();
+    public abstract void f514();
+    public abstract void f515();
+    public abstract void f516();
+    public abstract void f517();
+    public abstract void f518();
+    public abstract void f519();
+    public abstract void f520();
+    public abstract void f521();
+    public abstract void f522();
+    public abstract void f523();
+    public abstract void f524();
+    public abstract void f525();
+    public abstract void f526();
+    public abstract void f527();
+    public abstract void f528();
+    public abstract void f529();
+    public abstract void f530();
+    public abstract void f531();
+    public abstract void f532();
+    public abstract void f533();
+    public abstract void f534();
+    public abstract void f535();
+    public abstract void f536();
+    public abstract void f537();
+    public abstract void f538();
+    public abstract void f539();
+    public abstract void f540();
+    public abstract void f541();
+    public abstract void f542();
+    public abstract void f543();
+    public abstract void f544();
+    public abstract void f545();
+    public abstract void f546();
+    public abstract void f547();
+    public abstract void f548();
+    public abstract void f549();
+    public abstract void f550();
+    public abstract void f551();
+    public abstract void f552();
+    public abstract void f553();
+    public abstract void f554();
+    public abstract void f555();
+    public abstract void f556();
+    public abstract void f557();
+    public abstract void f558();
+    public abstract void f559();
+    public abstract void f560();
+    public abstract void f561();
+    public abstract void f562();
+    public abstract void f563();
+    public abstract void f564();
+    public abstract void f565();
+    public abstract void f566();
+    public abstract void f567();
+    public abstract void f568();
+    public abstract void f569();
+    public abstract void f570();
+    public abstract void f571();
+    public abstract void f572();
+    public abstract void f573();
+    public abstract void f574();
+    public abstract void f575();
+    public abstract void f576();
+    public abstract void f577();
+    public abstract void f578();
+    public abstract void f579();
+    public abstract void f580();
+    public abstract void f581();
+    public abstract void f582();
+    public abstract void f583();
+    public abstract void f584();
+    public abstract void f585();
+    public abstract void f586();
+    public abstract void f587();
+    public abstract void f588();
+    public abstract void f589();
+    public abstract void f590();
+    public abstract void f591();
+    public abstract void f592();
+    public abstract void f593();
+    public abstract void f594();
+    public abstract void f595();
+    public abstract void f596();
+    public abstract void f597();
+    public abstract void f598();
+    public abstract void f599();
+    public abstract void f600();
+    public abstract void f601();
+    public abstract void f602();
+    public abstract void f603();
+    public abstract void f604();
+    public abstract void f605();
+    public abstract void f606();
+    public abstract void f607();
+    public abstract void f608();
+    public abstract void f609();
+    public abstract void f610();
+    public abstract void f611();
+    public abstract void f612();
+    public abstract void f613();
+    public abstract void f614();
+    public abstract void f615();
+    public abstract void f616();
+    public abstract void f617();
+    public abstract void f618();
+    public abstract void f619();
+    public abstract void f620();
+    public abstract void f621();
+    public abstract void f622();
+    public abstract void f623();
+    public abstract void f624();
+    public abstract void f625();
+    public abstract void f626();
+    public abstract void f627();
+    public abstract void f628();
+    public abstract void f629();
+    public abstract void f630();
+    public abstract void f631();
+    public abstract void f632();
+    public abstract void f633();
+    public abstract void f634();
+    public abstract void f635();
+    public abstract void f636();
+    public abstract void f637();
+    public abstract void f638();
+    public abstract void f639();
+    public abstract void f640();
+    public abstract void f641();
+    public abstract void f642();
+    public abstract void f643();
+    public abstract void f644();
+    public abstract void f645();
+    public abstract void f646();
+    public abstract void f647();
+    public abstract void f648();
+    public abstract void f649();
+    public abstract void f650();
+    public abstract void f651();
+    public abstract void f652();
+    public abstract void f653();
+    public abstract void f654();
+    public abstract void f655();
+    public abstract void f656();
+    public abstract void f657();
+    public abstract void f658();
+    public abstract void f659();
+    public abstract void f660();
+    public abstract void f661();
+    public abstract void f662();
+    public abstract void f663();
+    public abstract void f664();
+    public abstract void f665();
+    public abstract void f666();
+    public abstract void f667();
+    public abstract void f668();
+    public abstract void f669();
+    public abstract void f670();
+    public abstract void f671();
+    public abstract void f672();
+    public abstract void f673();
+    public abstract void f674();
+    public abstract void f675();
+    public abstract void f676();
+    public abstract void f677();
+    public abstract void f678();
+    public abstract void f679();
+    public abstract void f680();
+    public abstract void f681();
+    public abstract void f682();
+    public abstract void f683();
+    public abstract void f684();
+    public abstract void f685();
+    public abstract void f686();
+    public abstract void f687();
+    public abstract void f688();
+    public abstract void f689();
+    public abstract void f690();
+    public abstract void f691();
+    public abstract void f692();
+    public abstract void f693();
+    public abstract void f694();
+    public abstract void f695();
+    public abstract void f696();
+    public abstract void f697();
+    public abstract void f698();
+    public abstract void f699();
+    public abstract void f700();
+    public abstract void f701();
+    public abstract void f702();
+    public abstract void f703();
+    public abstract void f704();
+    public abstract void f705();
+    public abstract void f706();
+    public abstract void f707();
+    public abstract void f708();
+    public abstract void f709();
+    public abstract void f710();
+    public abstract void f711();
+    public abstract void f712();
+    public abstract void f713();
+    public abstract void f714();
+    public abstract void f715();
+    public abstract void f716();
+    public abstract void f717();
+    public abstract void f718();
+    public abstract void f719();
+    public abstract void f720();
+    public abstract void f721();
+    public abstract void f722();
+    public abstract void f723();
+    public abstract void f724();
+    public abstract void f725();
+    public abstract void f726();
+    public abstract void f727();
+    public abstract void f728();
+    public abstract void f729();
+    public abstract void f730();
+    public abstract void f731();
+    public abstract void f732();
+    public abstract void f733();
+    public abstract void f734();
+    public abstract void f735();
+    public abstract void f736();
+    public abstract void f737();
+    public abstract void f738();
+    public abstract void f739();
+    public abstract void f740();
+    public abstract void f741();
+    public abstract void f742();
+    public abstract void f743();
+    public abstract void f744();
+    public abstract void f745();
+    public abstract void f746();
+    public abstract void f747();
+    public abstract void f748();
+    public abstract void f749();
+    public abstract void f750();
+    public abstract void f751();
+    public abstract void f752();
+    public abstract void f753();
+    public abstract void f754();
+    public abstract void f755();
+    public abstract void f756();
+    public abstract void f757();
+    public abstract void f758();
+    public abstract void f759();
+    public abstract void f760();
+    public abstract void f761();
+    public abstract void f762();
+    public abstract void f763();
+    public abstract void f764();
+    public abstract void f765();
+    public abstract void f766();
+    public abstract void f767();
+    public abstract void f768();
+    public abstract void f769();
+    public abstract void f770();
+    public abstract void f771();
+    public abstract void f772();
+    public abstract void f773();
+    public abstract void f774();
+    public abstract void f775();
+    public abstract void f776();
+    public abstract void f777();
+    public abstract void f778();
+    public abstract void f779();
+    public abstract void f780();
+    public abstract void f781();
+    public abstract void f782();
+    public abstract void f783();
+    public abstract void f784();
+    public abstract void f785();
+    public abstract void f786();
+    public abstract void f787();
+    public abstract void f788();
+    public abstract void f789();
+    public abstract void f790();
+    public abstract void f791();
+    public abstract void f792();
+    public abstract void f793();
+    public abstract void f794();
+    public abstract void f795();
+    public abstract void f796();
+    public abstract void f797();
+    public abstract void f798();
+    public abstract void f799();
+    public abstract void f800();
+    public abstract void f801();
+    public abstract void f802();
+    public abstract void f803();
+    public abstract void f804();
+    public abstract void f805();
+    public abstract void f806();
+    public abstract void f807();
+    public abstract void f808();
+    public abstract void f809();
+    public abstract void f810();
+    public abstract void f811();
+    public abstract void f812();
+    public abstract void f813();
+    public abstract void f814();
+    public abstract void f815();
+    public abstract void f816();
+    public abstract void f817();
+    public abstract void f818();
+    public abstract void f819();
+    public abstract void f820();
+    public abstract void f821();
+    public abstract void f822();
+    public abstract void f823();
+    public abstract void f824();
+    public abstract void f825();
+    public abstract void f826();
+    public abstract void f827();
+    public abstract void f828();
+    public abstract void f829();
+    public abstract void f830();
+    public abstract void f831();
+    public abstract void f832();
+    public abstract void f833();
+    public abstract void f834();
+    public abstract void f835();
+    public abstract void f836();
+    public abstract void f837();
+    public abstract void f838();
+    public abstract void f839();
+    public abstract void f840();
+    public abstract void f841();
+    public abstract void f842();
+    public abstract void f843();
+    public abstract void f844();
+    public abstract void f845();
+    public abstract void f846();
+    public abstract void f847();
+    public abstract void f848();
+    public abstract void f849();
+    public abstract void f850();
+    public abstract void f851();
+    public abstract void f852();
+    public abstract void f853();
+    public abstract void f854();
+    public abstract void f855();
+    public abstract void f856();
+    public abstract void f857();
+    public abstract void f858();
+    public abstract void f859();
+    public abstract void f860();
+    public abstract void f861();
+    public abstract void f862();
+    public abstract void f863();
+    public abstract void f864();
+    public abstract void f865();
+    public abstract void f866();
+    public abstract void f867();
+    public abstract void f868();
+    public abstract void f869();
+    public abstract void f870();
+    public abstract void f871();
+    public abstract void f872();
+    public abstract void f873();
+    public abstract void f874();
+    public abstract void f875();
+    public abstract void f876();
+    public abstract void f877();
+    public abstract void f878();
+    public abstract void f879();
+    public abstract void f880();
+    public abstract void f881();
+    public abstract void f882();
+    public abstract void f883();
+    public abstract void f884();
+    public abstract void f885();
+    public abstract void f886();
+    public abstract void f887();
+    public abstract void f888();
+    public abstract void f889();
+    public abstract void f890();
+    public abstract void f891();
+    public abstract void f892();
+    public abstract void f893();
+    public abstract void f894();
+    public abstract void f895();
+    public abstract void f896();
+    public abstract void f897();
+    public abstract void f898();
+    public abstract void f899();
+    public abstract void f900();
+    public abstract void f901();
+    public abstract void f902();
+    public abstract void f903();
+    public abstract void f904();
+    public abstract void f905();
+    public abstract void f906();
+    public abstract void f907();
+    public abstract void f908();
+    public abstract void f909();
+    public abstract void f910();
+    public abstract void f911();
+    public abstract void f912();
+    public abstract void f913();
+    public abstract void f914();
+    public abstract void f915();
+    public abstract void f916();
+    public abstract void f917();
+    public abstract void f918();
+    public abstract void f919();
+    public abstract void f920();
+    public abstract void f921();
+    public abstract void f922();
+    public abstract void f923();
+    public abstract void f924();
+    public abstract void f925();
+    public abstract void f926();
+    public abstract void f927();
+    public abstract void f928();
+    public abstract void f929();
+    public abstract void f930();
+    public abstract void f931();
+    public abstract void f932();
+    public abstract void f933();
+    public abstract void f934();
+    public abstract void f935();
+    public abstract void f936();
+    public abstract void f937();
+    public abstract void f938();
+    public abstract void f939();
+    public abstract void f940();
+    public abstract void f941();
+    public abstract void f942();
+    public abstract void f943();
+    public abstract void f944();
+    public abstract void f945();
+    public abstract void f946();
+    public abstract void f947();
+    public abstract void f948();
+    public abstract void f949();
+    public abstract void f950();
+    public abstract void f951();
+    public abstract void f952();
+    public abstract void f953();
+    public abstract void f954();
+    public abstract void f955();
+    public abstract void f956();
+    public abstract void f957();
+    public abstract void f958();
+    public abstract void f959();
+    public abstract void f960();
+    public abstract void f961();
+    public abstract void f962();
+    public abstract void f963();
+    public abstract void f964();
+    public abstract void f965();
+    public abstract void f966();
+    public abstract void f967();
+    public abstract void f968();
+    public abstract void f969();
+    public abstract void f970();
+    public abstract void f971();
+    public abstract void f972();
+    public abstract void f973();
+    public abstract void f974();
+    public abstract void f975();
+    public abstract void f976();
+    public abstract void f977();
+    public abstract void f978();
+    public abstract void f979();
+    public abstract void f980();
+    public abstract void f981();
+    public abstract void f982();
+    public abstract void f983();
+    public abstract void f984();
+    public abstract void f985();
+    public abstract void f986();
+    public abstract void f987();
+    public abstract void f988();
+    public abstract void f989();
+    public abstract void f990();
+    public abstract void f991();
+    public abstract void f992();
+    public abstract void f993();
+    public abstract void f994();
+    public abstract void f995();
+    public abstract void f996();
+    public abstract void f997();
+    public abstract void f998();
+    public abstract void f999();
+    public abstract void f1000();
+    public abstract void f1001();
+    public abstract void f1002();
+    public abstract void f1003();
+    public abstract void f1004();
+    public abstract void f1005();
+    public abstract void f1006();
+    public abstract void f1007();
+    public abstract void f1008();
+    public abstract void f1009();
+    public abstract void f1010();
+    public abstract void f1011();
+    public abstract void f1012();
+    public abstract void f1013();
+    public abstract void f1014();
+    public abstract void f1015();
+    public abstract void f1016();
+    public abstract void f1017();
+    public abstract void f1018();
+    public abstract void f1019();
+    public abstract void f1020();
+    public abstract void f1021();
+    public abstract void f1022();
+    public abstract void f1023();
+    public abstract void f1024();
+    public abstract void f1025();
+    public abstract void f1026();
+    public abstract void f1027();
+    public abstract void f1028();
+    public abstract void f1029();
+    public abstract void f1030();
+    public abstract void f1031();
+    public abstract void f1032();
+    public abstract void f1033();
+    public abstract void f1034();
+    public abstract void f1035();
+    public abstract void f1036();
+    public abstract void f1037();
+    public abstract void f1038();
+    public abstract void f1039();
+    public abstract void f1040();
+    public abstract void f1041();
+    public abstract void f1042();
+    public abstract void f1043();
+    public abstract void f1044();
+    public abstract void f1045();
+    public abstract void f1046();
+    public abstract void f1047();
+    public abstract void f1048();
+    public abstract void f1049();
+    public abstract void f1050();
+    public abstract void f1051();
+    public abstract void f1052();
+    public abstract void f1053();
+    public abstract void f1054();
+    public abstract void f1055();
+    public abstract void f1056();
+    public abstract void f1057();
+    public abstract void f1058();
+    public abstract void f1059();
+    public abstract void f1060();
+    public abstract void f1061();
+    public abstract void f1062();
+    public abstract void f1063();
+    public abstract void f1064();
+    public abstract void f1065();
+    public abstract void f1066();
+    public abstract void f1067();
+    public abstract void f1068();
+    public abstract void f1069();
+    public abstract void f1070();
+    public abstract void f1071();
+    public abstract void f1072();
+    public abstract void f1073();
+    public abstract void f1074();
+    public abstract void f1075();
+    public abstract void f1076();
+    public abstract void f1077();
+    public abstract void f1078();
+    public abstract void f1079();
+    public abstract void f1080();
+    public abstract void f1081();
+    public abstract void f1082();
+    public abstract void f1083();
+    public abstract void f1084();
+    public abstract void f1085();
+    public abstract void f1086();
+    public abstract void f1087();
+    public abstract void f1088();
+    public abstract void f1089();
+    public abstract void f1090();
+    public abstract void f1091();
+    public abstract void f1092();
+    public abstract void f1093();
+    public abstract void f1094();
+    public abstract void f1095();
+    public abstract void f1096();
+    public abstract void f1097();
+    public abstract void f1098();
+    public abstract void f1099();
+    public abstract void f1100();
+    public abstract void f1101();
+    public abstract void f1102();
+    public abstract void f1103();
+    public abstract void f1104();
+    public abstract void f1105();
+    public abstract void f1106();
+    public abstract void f1107();
+    public abstract void f1108();
+    public abstract void f1109();
+    public abstract void f1110();
+    public abstract void f1111();
+    public abstract void f1112();
+    public abstract void f1113();
+    public abstract void f1114();
+    public abstract void f1115();
+    public abstract void f1116();
+    public abstract void f1117();
+    public abstract void f1118();
+    public abstract void f1119();
+    public abstract void f1120();
+    public abstract void f1121();
+    public abstract void f1122();
+    public abstract void f1123();
+    public abstract void f1124();
+    public abstract void f1125();
+    public abstract void f1126();
+    public abstract void f1127();
+    public abstract void f1128();
+    public abstract void f1129();
+    public abstract void f1130();
+    public abstract void f1131();
+    public abstract void f1132();
+    public abstract void f1133();
+    public abstract void f1134();
+    public abstract void f1135();
+    public abstract void f1136();
+    public abstract void f1137();
+    public abstract void f1138();
+    public abstract void f1139();
+    public abstract void f1140();
+    public abstract void f1141();
+    public abstract void f1142();
+    public abstract void f1143();
+    public abstract void f1144();
+    public abstract void f1145();
+    public abstract void f1146();
+    public abstract void f1147();
+    public abstract void f1148();
+    public abstract void f1149();
+    public abstract void f1150();
+    public abstract void f1151();
+    public abstract void f1152();
+    public abstract void f1153();
+    public abstract void f1154();
+    public abstract void f1155();
+    public abstract void f1156();
+    public abstract void f1157();
+    public abstract void f1158();
+    public abstract void f1159();
+    public abstract void f1160();
+    public abstract void f1161();
+    public abstract void f1162();
+    public abstract void f1163();
+    public abstract void f1164();
+    public abstract void f1165();
+    public abstract void f1166();
+    public abstract void f1167();
+    public abstract void f1168();
+    public abstract void f1169();
+    public abstract void f1170();
+    public abstract void f1171();
+    public abstract void f1172();
+    public abstract void f1173();
+    public abstract void f1174();
+    public abstract void f1175();
+    public abstract void f1176();
+    public abstract void f1177();
+    public abstract void f1178();
+    public abstract void f1179();
+    public abstract void f1180();
+    public abstract void f1181();
+    public abstract void f1182();
+    public abstract void f1183();
+    public abstract void f1184();
+    public abstract void f1185();
+    public abstract void f1186();
+    public abstract void f1187();
+    public abstract void f1188();
+    public abstract void f1189();
+    public abstract void f1190();
+    public abstract void f1191();
+    public abstract void f1192();
+    public abstract void f1193();
+    public abstract void f1194();
+    public abstract void f1195();
+    public abstract void f1196();
+    public abstract void f1197();
+    public abstract void f1198();
+    public abstract void f1199();
+    public abstract void f1200();
+    public abstract void f1201();
+    public abstract void f1202();
+    public abstract void f1203();
+    public abstract void f1204();
+    public abstract void f1205();
+    public abstract void f1206();
+    public abstract void f1207();
+    public abstract void f1208();
+    public abstract void f1209();
+    public abstract void f1210();
+    public abstract void f1211();
+    public abstract void f1212();
+    public abstract void f1213();
+    public abstract void f1214();
+    public abstract void f1215();
+    public abstract void f1216();
+    public abstract void f1217();
+    public abstract void f1218();
+    public abstract void f1219();
+    public abstract void f1220();
+    public abstract void f1221();
+    public abstract void f1222();
+    public abstract void f1223();
+    public abstract void f1224();
+    public abstract void f1225();
+    public abstract void f1226();
+    public abstract void f1227();
+    public abstract void f1228();
+    public abstract void f1229();
+    public abstract void f1230();
+    public abstract void f1231();
+    public abstract void f1232();
+    public abstract void f1233();
+    public abstract void f1234();
+    public abstract void f1235();
+    public abstract void f1236();
+    public abstract void f1237();
+    public abstract void f1238();
+    public abstract void f1239();
+    public abstract void f1240();
+    public abstract void f1241();
+    public abstract void f1242();
+    public abstract void f1243();
+    public abstract void f1244();
+    public abstract void f1245();
+    public abstract void f1246();
+    public abstract void f1247();
+    public abstract void f1248();
+    public abstract void f1249();
+    public abstract void f1250();
+    public abstract void f1251();
+    public abstract void f1252();
+    public abstract void f1253();
+    public abstract void f1254();
+    public abstract void f1255();
+    public abstract void f1256();
+    public abstract void f1257();
+    public abstract void f1258();
+    public abstract void f1259();
+    public abstract void f1260();
+    public abstract void f1261();
+    public abstract void f1262();
+    public abstract void f1263();
+    public abstract void f1264();
+    public abstract void f1265();
+    public abstract void f1266();
+    public abstract void f1267();
+    public abstract void f1268();
+    public abstract void f1269();
+    public abstract void f1270();
+    public abstract void f1271();
+    public abstract void f1272();
+    public abstract void f1273();
+    public abstract void f1274();
+    public abstract void f1275();
+    public abstract void f1276();
+    public abstract void f1277();
+    public abstract void f1278();
+    public abstract void f1279();
+    public abstract void f1280();
+    public abstract void f1281();
+    public abstract void f1282();
+    public abstract void f1283();
+    public abstract void f1284();
+    public abstract void f1285();
+    public abstract void f1286();
+    public abstract void f1287();
+    public abstract void f1288();
+    public abstract void f1289();
+    public abstract void f1290();
+    public abstract void f1291();
+    public abstract void f1292();
+    public abstract void f1293();
+    public abstract void f1294();
+    public abstract void f1295();
+    public abstract void f1296();
+    public abstract void f1297();
+    public abstract void f1298();
+    public abstract void f1299();
+    public abstract void f1300();
+    public abstract void f1301();
+    public abstract void f1302();
+    public abstract void f1303();
+    public abstract void f1304();
+    public abstract void f1305();
+    public abstract void f1306();
+    public abstract void f1307();
+    public abstract void f1308();
+    public abstract void f1309();
+    public abstract void f1310();
+    public abstract void f1311();
+    public abstract void f1312();
+    public abstract void f1313();
+    public abstract void f1314();
+    public abstract void f1315();
+    public abstract void f1316();
+    public abstract void f1317();
+    public abstract void f1318();
+    public abstract void f1319();
+    public abstract void f1320();
+    public abstract void f1321();
+    public abstract void f1322();
+    public abstract void f1323();
+    public abstract void f1324();
+    public abstract void f1325();
+    public abstract void f1326();
+    public abstract void f1327();
+    public abstract void f1328();
+    public abstract void f1329();
+    public abstract void f1330();
+    public abstract void f1331();
+    public abstract void f1332();
+    public abstract void f1333();
+    public abstract void f1334();
+    public abstract void f1335();
+    public abstract void f1336();
+    public abstract void f1337();
+    public abstract void f1338();
+    public abstract void f1339();
+    public abstract void f1340();
+    public abstract void f1341();
+    public abstract void f1342();
+    public abstract void f1343();
+    public abstract void f1344();
+    public abstract void f1345();
+    public abstract void f1346();
+    public abstract void f1347();
+    public abstract void f1348();
+    public abstract void f1349();
+    public abstract void f1350();
+    public abstract void f1351();
+    public abstract void f1352();
+    public abstract void f1353();
+    public abstract void f1354();
+    public abstract void f1355();
+    public abstract void f1356();
+    public abstract void f1357();
+    public abstract void f1358();
+    public abstract void f1359();
+    public abstract void f1360();
+    public abstract void f1361();
+    public abstract void f1362();
+    public abstract void f1363();
+    public abstract void f1364();
+    public abstract void f1365();
+    public abstract void f1366();
+    public abstract void f1367();
+    public abstract void f1368();
+    public abstract void f1369();
+    public abstract void f1370();
+    public abstract void f1371();
+    public abstract void f1372();
+    public abstract void f1373();
+    public abstract void f1374();
+    public abstract void f1375();
+    public abstract void f1376();
+    public abstract void f1377();
+    public abstract void f1378();
+    public abstract void f1379();
+    public abstract void f1380();
+    public abstract void f1381();
+    public abstract void f1382();
+    public abstract void f1383();
+    public abstract void f1384();
+    public abstract void f1385();
+    public abstract void f1386();
+    public abstract void f1387();
+    public abstract void f1388();
+    public abstract void f1389();
+    public abstract void f1390();
+    public abstract void f1391();
+    public abstract void f1392();
+    public abstract void f1393();
+    public abstract void f1394();
+    public abstract void f1395();
+    public abstract void f1396();
+    public abstract void f1397();
+    public abstract void f1398();
+    public abstract void f1399();
+    public abstract void f1400();
+    public abstract void f1401();
+    public abstract void f1402();
+    public abstract void f1403();
+    public abstract void f1404();
+    public abstract void f1405();
+    public abstract void f1406();
+    public abstract void f1407();
+    public abstract void f1408();
+    public abstract void f1409();
+    public abstract void f1410();
+    public abstract void f1411();
+    public abstract void f1412();
+    public abstract void f1413();
+    public abstract void f1414();
+    public abstract void f1415();
+    public abstract void f1416();
+    public abstract void f1417();
+    public abstract void f1418();
+    public abstract void f1419();
+    public abstract void f1420();
+    public abstract void f1421();
+    public abstract void f1422();
+    public abstract void f1423();
+    public abstract void f1424();
+    public abstract void f1425();
+    public abstract void f1426();
+    public abstract void f1427();
+    public abstract void f1428();
+    public abstract void f1429();
+    public abstract void f1430();
+    public abstract void f1431();
+    public abstract void f1432();
+    public abstract void f1433();
+    public abstract void f1434();
+    public abstract void f1435();
+    public abstract void f1436();
+    public abstract void f1437();
+    public abstract void f1438();
+    public abstract void f1439();
+    public abstract void f1440();
+    public abstract void f1441();
+    public abstract void f1442();
+    public abstract void f1443();
+    public abstract void f1444();
+    public abstract void f1445();
+    public abstract void f1446();
+    public abstract void f1447();
+    public abstract void f1448();
+    public abstract void f1449();
+    public abstract void f1450();
+    public abstract void f1451();
+    public abstract void f1452();
+    public abstract void f1453();
+    public abstract void f1454();
+    public abstract void f1455();
+    public abstract void f1456();
+    public abstract void f1457();
+    public abstract void f1458();
+    public abstract void f1459();
+    public abstract void f1460();
+    public abstract void f1461();
+    public abstract void f1462();
+    public abstract void f1463();
+    public abstract void f1464();
+    public abstract void f1465();
+    public abstract void f1466();
+    public abstract void f1467();
+    public abstract void f1468();
+    public abstract void f1469();
+    public abstract void f1470();
+    public abstract void f1471();
+    public abstract void f1472();
+    public abstract void f1473();
+    public abstract void f1474();
+    public abstract void f1475();
+    public abstract void f1476();
+    public abstract void f1477();
+    public abstract void f1478();
+    public abstract void f1479();
+    public abstract void f1480();
+    public abstract void f1481();
+    public abstract void f1482();
+    public abstract void f1483();
+    public abstract void f1484();
+    public abstract void f1485();
+    public abstract void f1486();
+    public abstract void f1487();
+    public abstract void f1488();
+    public abstract void f1489();
+    public abstract void f1490();
+    public abstract void f1491();
+    public abstract void f1492();
+    public abstract void f1493();
+    public abstract void f1494();
+    public abstract void f1495();
+    public abstract void f1496();
+    public abstract void f1497();
+    public abstract void f1498();
+    public abstract void f1499();
+    public abstract void f1500();
+    public abstract void f1501();
+    public abstract void f1502();
+    public abstract void f1503();
+    public abstract void f1504();
+    public abstract void f1505();
+    public abstract void f1506();
+    public abstract void f1507();
+    public abstract void f1508();
+    public abstract void f1509();
+    public abstract void f1510();
+    public abstract void f1511();
+    public abstract void f1512();
+    public abstract void f1513();
+    public abstract void f1514();
+    public abstract void f1515();
+    public abstract void f1516();
+    public abstract void f1517();
+    public abstract void f1518();
+    public abstract void f1519();
+    public abstract void f1520();
+    public abstract void f1521();
+    public abstract void f1522();
+    public abstract void f1523();
+    public abstract void f1524();
+    public abstract void f1525();
+    public abstract void f1526();
+    public abstract void f1527();
+    public abstract void f1528();
+    public abstract void f1529();
+    public abstract void f1530();
+    public abstract void f1531();
+    public abstract void f1532();
+    public abstract void f1533();
+    public abstract void f1534();
+    public abstract void f1535();
+    public abstract void f1536();
+    public abstract void f1537();
+    public abstract void f1538();
+    public abstract void f1539();
+    public abstract void f1540();
+    public abstract void f1541();
+    public abstract void f1542();
+    public abstract void f1543();
+    public abstract void f1544();
+    public abstract void f1545();
+    public abstract void f1546();
+    public abstract void f1547();
+    public abstract void f1548();
+    public abstract void f1549();
+    public abstract void f1550();
+    public abstract void f1551();
+    public abstract void f1552();
+    public abstract void f1553();
+    public abstract void f1554();
+    public abstract void f1555();
+    public abstract void f1556();
+    public abstract void f1557();
+    public abstract void f1558();
+    public abstract void f1559();
+    public abstract void f1560();
+    public abstract void f1561();
+    public abstract void f1562();
+    public abstract void f1563();
+    public abstract void f1564();
+    public abstract void f1565();
+    public abstract void f1566();
+    public abstract void f1567();
+    public abstract void f1568();
+    public abstract void f1569();
+    public abstract void f1570();
+    public abstract void f1571();
+    public abstract void f1572();
+    public abstract void f1573();
+    public abstract void f1574();
+    public abstract void f1575();
+    public abstract void f1576();
+    public abstract void f1577();
+    public abstract void f1578();
+    public abstract void f1579();
+    public abstract void f1580();
+    public abstract void f1581();
+    public abstract void f1582();
+    public abstract void f1583();
+    public abstract void f1584();
+    public abstract void f1585();
+    public abstract void f1586();
+    public abstract void f1587();
+    public abstract void f1588();
+    public abstract void f1589();
+    public abstract void f1590();
+    public abstract void f1591();
+    public abstract void f1592();
+    public abstract void f1593();
+    public abstract void f1594();
+    public abstract void f1595();
+    public abstract void f1596();
+    public abstract void f1597();
+    public abstract void f1598();
+    public abstract void f1599();
+    public abstract void f1600();
+    public abstract void f1601();
+    public abstract void f1602();
+    public abstract void f1603();
+    public abstract void f1604();
+    public abstract void f1605();
+    public abstract void f1606();
+    public abstract void f1607();
+    public abstract void f1608();
+    public abstract void f1609();
+    public abstract void f1610();
+    public abstract void f1611();
+    public abstract void f1612();
+    public abstract void f1613();
+    public abstract void f1614();
+    public abstract void f1615();
+    public abstract void f1616();
+    public abstract void f1617();
+    public abstract void f1618();
+    public abstract void f1619();
+    public abstract void f1620();
+    public abstract void f1621();
+    public abstract void f1622();
+    public abstract void f1623();
+    public abstract void f1624();
+    public abstract void f1625();
+    public abstract void f1626();
+    public abstract void f1627();
+    public abstract void f1628();
+    public abstract void f1629();
+    public abstract void f1630();
+    public abstract void f1631();
+    public abstract void f1632();
+    public abstract void f1633();
+    public abstract void f1634();
+    public abstract void f1635();
+    public abstract void f1636();
+    public abstract void f1637();
+    public abstract void f1638();
+    public abstract void f1639();
+    public abstract void f1640();
+    public abstract void f1641();
+    public abstract void f1642();
+    public abstract void f1643();
+    public abstract void f1644();
+    public abstract void f1645();
+    public abstract void f1646();
+    public abstract void f1647();
+    public abstract void f1648();
+    public abstract void f1649();
+    public abstract void f1650();
+    public abstract void f1651();
+    public abstract void f1652();
+    public abstract void f1653();
+    public abstract void f1654();
+    public abstract void f1655();
+    public abstract void f1656();
+    public abstract void f1657();
+    public abstract void f1658();
+    public abstract void f1659();
+    public abstract void f1660();
+    public abstract void f1661();
+    public abstract void f1662();
+    public abstract void f1663();
+    public abstract void f1664();
+    public abstract void f1665();
+    public abstract void f1666();
+    public abstract void f1667();
+    public abstract void f1668();
+    public abstract void f1669();
+    public abstract void f1670();
+    public abstract void f1671();
+    public abstract void f1672();
+    public abstract void f1673();
+    public abstract void f1674();
+    public abstract void f1675();
+    public abstract void f1676();
+    public abstract void f1677();
+    public abstract void f1678();
+    public abstract void f1679();
+    public abstract void f1680();
+    public abstract void f1681();
+    public abstract void f1682();
+    public abstract void f1683();
+    public abstract void f1684();
+    public abstract void f1685();
+    public abstract void f1686();
+    public abstract void f1687();
+    public abstract void f1688();
+    public abstract void f1689();
+    public abstract void f1690();
+    public abstract void f1691();
+    public abstract void f1692();
+    public abstract void f1693();
+    public abstract void f1694();
+    public abstract void f1695();
+    public abstract void f1696();
+    public abstract void f1697();
+    public abstract void f1698();
+    public abstract void f1699();
+    public abstract void f1700();
+    public abstract void f1701();
+    public abstract void f1702();
+    public abstract void f1703();
+    public abstract void f1704();
+    public abstract void f1705();
+    public abstract void f1706();
+    public abstract void f1707();
+    public abstract void f1708();
+    public abstract void f1709();
+    public abstract void f1710();
+    public abstract void f1711();
+    public abstract void f1712();
+    public abstract void f1713();
+    public abstract void f1714();
+    public abstract void f1715();
+    public abstract void f1716();
+    public abstract void f1717();
+    public abstract void f1718();
+    public abstract void f1719();
+    public abstract void f1720();
+    public abstract void f1721();
+    public abstract void f1722();
+    public abstract void f1723();
+    public abstract void f1724();
+    public abstract void f1725();
+    public abstract void f1726();
+    public abstract void f1727();
+    public abstract void f1728();
+    public abstract void f1729();
+    public abstract void f1730();
+    public abstract void f1731();
+    public abstract void f1732();
+    public abstract void f1733();
+    public abstract void f1734();
+    public abstract void f1735();
+    public abstract void f1736();
+    public abstract void f1737();
+    public abstract void f1738();
+    public abstract void f1739();
+    public abstract void f1740();
+    public abstract void f1741();
+    public abstract void f1742();
+    public abstract void f1743();
+    public abstract void f1744();
+    public abstract void f1745();
+    public abstract void f1746();
+    public abstract void f1747();
+    public abstract void f1748();
+    public abstract void f1749();
+    public abstract void f1750();
+    public abstract void f1751();
+    public abstract void f1752();
+    public abstract void f1753();
+    public abstract void f1754();
+    public abstract void f1755();
+    public abstract void f1756();
+    public abstract void f1757();
+    public abstract void f1758();
+    public abstract void f1759();
+    public abstract void f1760();
+    public abstract void f1761();
+    public abstract void f1762();
+    public abstract void f1763();
+    public abstract void f1764();
+    public abstract void f1765();
+    public abstract void f1766();
+    public abstract void f1767();
+    public abstract void f1768();
+    public abstract void f1769();
+    public abstract void f1770();
+    public abstract void f1771();
+    public abstract void f1772();
+    public abstract void f1773();
+    public abstract void f1774();
+    public abstract void f1775();
+    public abstract void f1776();
+    public abstract void f1777();
+    public abstract void f1778();
+    public abstract void f1779();
+    public abstract void f1780();
+    public abstract void f1781();
+    public abstract void f1782();
+    public abstract void f1783();
+    public abstract void f1784();
+    public abstract void f1785();
+    public abstract void f1786();
+    public abstract void f1787();
+    public abstract void f1788();
+    public abstract void f1789();
+    public abstract void f1790();
+    public abstract void f1791();
+    public abstract void f1792();
+    public abstract void f1793();
+    public abstract void f1794();
+    public abstract void f1795();
+    public abstract void f1796();
+    public abstract void f1797();
+    public abstract void f1798();
+    public abstract void f1799();
+    public abstract void f1800();
+    public abstract void f1801();
+    public abstract void f1802();
+    public abstract void f1803();
+    public abstract void f1804();
+    public abstract void f1805();
+    public abstract void f1806();
+    public abstract void f1807();
+    public abstract void f1808();
+    public abstract void f1809();
+    public abstract void f1810();
+    public abstract void f1811();
+    public abstract void f1812();
+    public abstract void f1813();
+    public abstract void f1814();
+    public abstract void f1815();
+    public abstract void f1816();
+    public abstract void f1817();
+    public abstract void f1818();
+    public abstract void f1819();
+    public abstract void f1820();
+    public abstract void f1821();
+    public abstract void f1822();
+    public abstract void f1823();
+    public abstract void f1824();
+    public abstract void f1825();
+    public abstract void f1826();
+    public abstract void f1827();
+    public abstract void f1828();
+    public abstract void f1829();
+    public abstract void f1830();
+    public abstract void f1831();
+    public abstract void f1832();
+    public abstract void f1833();
+    public abstract void f1834();
+    public abstract void f1835();
+    public abstract void f1836();
+    public abstract void f1837();
+    public abstract void f1838();
+    public abstract void f1839();
+    public abstract void f1840();
+    public abstract void f1841();
+    public abstract void f1842();
+    public abstract void f1843();
+    public abstract void f1844();
+    public abstract void f1845();
+    public abstract void f1846();
+    public abstract void f1847();
+    public abstract void f1848();
+    public abstract void f1849();
+    public abstract void f1850();
+    public abstract void f1851();
+    public abstract void f1852();
+    public abstract void f1853();
+    public abstract void f1854();
+    public abstract void f1855();
+    public abstract void f1856();
+    public abstract void f1857();
+    public abstract void f1858();
+    public abstract void f1859();
+    public abstract void f1860();
+    public abstract void f1861();
+    public abstract void f1862();
+    public abstract void f1863();
+    public abstract void f1864();
+    public abstract void f1865();
+    public abstract void f1866();
+    public abstract void f1867();
+    public abstract void f1868();
+    public abstract void f1869();
+    public abstract void f1870();
+    public abstract void f1871();
+    public abstract void f1872();
+    public abstract void f1873();
+    public abstract void f1874();
+    public abstract void f1875();
+    public abstract void f1876();
+    public abstract void f1877();
+    public abstract void f1878();
+    public abstract void f1879();
+    public abstract void f1880();
+    public abstract void f1881();
+    public abstract void f1882();
+    public abstract void f1883();
+    public abstract void f1884();
+    public abstract void f1885();
+    public abstract void f1886();
+    public abstract void f1887();
+    public abstract void f1888();
+    public abstract void f1889();
+    public abstract void f1890();
+    public abstract void f1891();
+    public abstract void f1892();
+    public abstract void f1893();
+    public abstract void f1894();
+    public abstract void f1895();
+    public abstract void f1896();
+    public abstract void f1897();
+    public abstract void f1898();
+    public abstract void f1899();
+    public abstract void f1900();
+    public abstract void f1901();
+    public abstract void f1902();
+    public abstract void f1903();
+    public abstract void f1904();
+    public abstract void f1905();
+    public abstract void f1906();
+    public abstract void f1907();
+    public abstract void f1908();
+    public abstract void f1909();
+    public abstract void f1910();
+    public abstract void f1911();
+    public abstract void f1912();
+    public abstract void f1913();
+    public abstract void f1914();
+    public abstract void f1915();
+    public abstract void f1916();
+    public abstract void f1917();
+    public abstract void f1918();
+    public abstract void f1919();
+    public abstract void f1920();
+    public abstract void f1921();
+    public abstract void f1922();
+    public abstract void f1923();
+    public abstract void f1924();
+    public abstract void f1925();
+    public abstract void f1926();
+    public abstract void f1927();
+    public abstract void f1928();
+    public abstract void f1929();
+    public abstract void f1930();
+    public abstract void f1931();
+    public abstract void f1932();
+    public abstract void f1933();
+    public abstract void f1934();
+    public abstract void f1935();
+    public abstract void f1936();
+    public abstract void f1937();
+    public abstract void f1938();
+    public abstract void f1939();
+    public abstract void f1940();
+    public abstract void f1941();
+    public abstract void f1942();
+    public abstract void f1943();
+    public abstract void f1944();
+    public abstract void f1945();
+    public abstract void f1946();
+    public abstract void f1947();
+    public abstract void f1948();
+    public abstract void f1949();
+    public abstract void f1950();
+    public abstract void f1951();
+    public abstract void f1952();
+    public abstract void f1953();
+    public abstract void f1954();
+    public abstract void f1955();
+    public abstract void f1956();
+    public abstract void f1957();
+    public abstract void f1958();
+    public abstract void f1959();
+    public abstract void f1960();
+    public abstract void f1961();
+    public abstract void f1962();
+    public abstract void f1963();
+    public abstract void f1964();
+    public abstract void f1965();
+    public abstract void f1966();
+    public abstract void f1967();
+    public abstract void f1968();
+    public abstract void f1969();
+    public abstract void f1970();
+    public abstract void f1971();
+    public abstract void f1972();
+    public abstract void f1973();
+    public abstract void f1974();
+    public abstract void f1975();
+    public abstract void f1976();
+    public abstract void f1977();
+    public abstract void f1978();
+    public abstract void f1979();
+    public abstract void f1980();
+    public abstract void f1981();
+    public abstract void f1982();
+    public abstract void f1983();
+    public abstract void f1984();
+    public abstract void f1985();
+    public abstract void f1986();
+    public abstract void f1987();
+    public abstract void f1988();
+    public abstract void f1989();
+    public abstract void f1990();
+    public abstract void f1991();
+    public abstract void f1992();
+    public abstract void f1993();
+    public abstract void f1994();
+    public abstract void f1995();
+    public abstract void f1996();
+    public abstract void f1997();
+    public abstract void f1998();
+    public abstract void f1999();
+    public abstract void f2000();
+    public abstract void f2001();
+    public abstract void f2002();
+    public abstract void f2003();
+    public abstract void f2004();
+    public abstract void f2005();
+    public abstract void f2006();
+    public abstract void f2007();
+    public abstract void f2008();
+    public abstract void f2009();
+    public abstract void f2010();
+    public abstract void f2011();
+    public abstract void f2012();
+    public abstract void f2013();
+    public abstract void f2014();
+    public abstract void f2015();
+    public abstract void f2016();
+    public abstract void f2017();
+    public abstract void f2018();
+    public abstract void f2019();
+    public abstract void f2020();
+    public abstract void f2021();
+    public abstract void f2022();
+    public abstract void f2023();
+    public abstract void f2024();
+    public abstract void f2025();
+    public abstract void f2026();
+    public abstract void f2027();
+    public abstract void f2028();
+    public abstract void f2029();
+    public abstract void f2030();
+    public abstract void f2031();
+    public abstract void f2032();
+    public abstract void f2033();
+    public abstract void f2034();
+    public abstract void f2035();
+    public abstract void f2036();
+    public abstract void f2037();
+    public abstract void f2038();
+    public abstract void f2039();
+    public abstract void f2040();
+    public abstract void f2041();
+    public abstract void f2042();
+    public abstract void f2043();
+    public abstract void f2044();
+    public abstract void f2045();
+    public abstract void f2046();
+    public abstract void f2047();
+    public abstract void f2048();
+    public abstract void f2049();
+    public abstract void f2050();
+    public abstract void f2051();
+    public abstract void f2052();
+    public abstract void f2053();
+    public abstract void f2054();
+    public abstract void f2055();
+    public abstract void f2056();
+    public abstract void f2057();
+    public abstract void f2058();
+    public abstract void f2059();
+    public abstract void f2060();
+    public abstract void f2061();
+    public abstract void f2062();
+    public abstract void f2063();
+    public abstract void f2064();
+    public abstract void f2065();
+    public abstract void f2066();
+    public abstract void f2067();
+    public abstract void f2068();
+    public abstract void f2069();
+    public abstract void f2070();
+    public abstract void f2071();
+    public abstract void f2072();
+    public abstract void f2073();
+    public abstract void f2074();
+    public abstract void f2075();
+    public abstract void f2076();
+    public abstract void f2077();
+    public abstract void f2078();
+    public abstract void f2079();
+    public abstract void f2080();
+    public abstract void f2081();
+    public abstract void f2082();
+    public abstract void f2083();
+    public abstract void f2084();
+    public abstract void f2085();
+    public abstract void f2086();
+    public abstract void f2087();
+    public abstract void f2088();
+    public abstract void f2089();
+    public abstract void f2090();
+    public abstract void f2091();
+    public abstract void f2092();
+    public abstract void f2093();
+    public abstract void f2094();
+    public abstract void f2095();
+    public abstract void f2096();
+    public abstract void f2097();
+    public abstract void f2098();
+    public abstract void f2099();
+    public abstract void f2100();
+    public abstract void f2101();
+    public abstract void f2102();
+    public abstract void f2103();
+    public abstract void f2104();
+    public abstract void f2105();
+    public abstract void f2106();
+    public abstract void f2107();
+    public abstract void f2108();
+    public abstract void f2109();
+    public abstract void f2110();
+    public abstract void f2111();
+    public abstract void f2112();
+    public abstract void f2113();
+    public abstract void f2114();
+    public abstract void f2115();
+    public abstract void f2116();
+    public abstract void f2117();
+    public abstract void f2118();
+    public abstract void f2119();
+    public abstract void f2120();
+    public abstract void f2121();
+    public abstract void f2122();
+    public abstract void f2123();
+    public abstract void f2124();
+    public abstract void f2125();
+    public abstract void f2126();
+    public abstract void f2127();
+    public abstract void f2128();
+    public abstract void f2129();
+    public abstract void f2130();
+    public abstract void f2131();
+    public abstract void f2132();
+    public abstract void f2133();
+    public abstract void f2134();
+    public abstract void f2135();
+    public abstract void f2136();
+    public abstract void f2137();
+    public abstract void f2138();
+    public abstract void f2139();
+    public abstract void f2140();
+    public abstract void f2141();
+    public abstract void f2142();
+    public abstract void f2143();
+    public abstract void f2144();
+    public abstract void f2145();
+    public abstract void f2146();
+    public abstract void f2147();
+    public abstract void f2148();
+    public abstract void f2149();
+    public abstract void f2150();
+    public abstract void f2151();
+    public abstract void f2152();
+    public abstract void f2153();
+    public abstract void f2154();
+    public abstract void f2155();
+    public abstract void f2156();
+    public abstract void f2157();
+    public abstract void f2158();
+    public abstract void f2159();
+    public abstract void f2160();
+    public abstract void f2161();
+    public abstract void f2162();
+    public abstract void f2163();
+    public abstract void f2164();
+    public abstract void f2165();
+    public abstract void f2166();
+    public abstract void f2167();
+    public abstract void f2168();
+    public abstract void f2169();
+    public abstract void f2170();
+    public abstract void f2171();
+    public abstract void f2172();
+    public abstract void f2173();
+    public abstract void f2174();
+    public abstract void f2175();
+    public abstract void f2176();
+    public abstract void f2177();
+    public abstract void f2178();
+    public abstract void f2179();
+    public abstract void f2180();
+    public abstract void f2181();
+    public abstract void f2182();
+    public abstract void f2183();
+    public abstract void f2184();
+    public abstract void f2185();
+    public abstract void f2186();
+    public abstract void f2187();
+    public abstract void f2188();
+    public abstract void f2189();
+    public abstract void f2190();
+    public abstract void f2191();
+    public abstract void f2192();
+    public abstract void f2193();
+    public abstract void f2194();
+    public abstract void f2195();
+    public abstract void f2196();
+    public abstract void f2197();
+    public abstract void f2198();
+    public abstract void f2199();
+    public abstract void f2200();
+    public abstract void f2201();
+    public abstract void f2202();
+    public abstract void f2203();
+    public abstract void f2204();
+    public abstract void f2205();
+    public abstract void f2206();
+    public abstract void f2207();
+    public abstract void f2208();
+    public abstract void f2209();
+    public abstract void f2210();
+    public abstract void f2211();
+    public abstract void f2212();
+    public abstract void f2213();
+    public abstract void f2214();
+    public abstract void f2215();
+    public abstract void f2216();
+    public abstract void f2217();
+    public abstract void f2218();
+    public abstract void f2219();
+    public abstract void f2220();
+    public abstract void f2221();
+    public abstract void f2222();
+    public abstract void f2223();
+    public abstract void f2224();
+    public abstract void f2225();
+    public abstract void f2226();
+    public abstract void f2227();
+    public abstract void f2228();
+    public abstract void f2229();
+    public abstract void f2230();
+    public abstract void f2231();
+    public abstract void f2232();
+    public abstract void f2233();
+    public abstract void f2234();
+    public abstract void f2235();
+    public abstract void f2236();
+    public abstract void f2237();
+    public abstract void f2238();
+    public abstract void f2239();
+    public abstract void f2240();
+    public abstract void f2241();
+    public abstract void f2242();
+    public abstract void f2243();
+    public abstract void f2244();
+    public abstract void f2245();
+    public abstract void f2246();
+    public abstract void f2247();
+    public abstract void f2248();
+    public abstract void f2249();
+    public abstract void f2250();
+    public abstract void f2251();
+    public abstract void f2252();
+    public abstract void f2253();
+    public abstract void f2254();
+    public abstract void f2255();
+    public abstract void f2256();
+    public abstract void f2257();
+    public abstract void f2258();
+    public abstract void f2259();
+    public abstract void f2260();
+    public abstract void f2261();
+    public abstract void f2262();
+    public abstract void f2263();
+    public abstract void f2264();
+    public abstract void f2265();
+    public abstract void f2266();
+    public abstract void f2267();
+    public abstract void f2268();
+    public abstract void f2269();
+    public abstract void f2270();
+    public abstract void f2271();
+    public abstract void f2272();
+    public abstract void f2273();
+    public abstract void f2274();
+    public abstract void f2275();
+    public abstract void f2276();
+    public abstract void f2277();
+    public abstract void f2278();
+    public abstract void f2279();
+    public abstract void f2280();
+    public abstract void f2281();
+    public abstract void f2282();
+    public abstract void f2283();
+    public abstract void f2284();
+    public abstract void f2285();
+    public abstract void f2286();
+    public abstract void f2287();
+    public abstract void f2288();
+    public abstract void f2289();
+    public abstract void f2290();
+    public abstract void f2291();
+    public abstract void f2292();
+    public abstract void f2293();
+    public abstract void f2294();
+    public abstract void f2295();
+    public abstract void f2296();
+    public abstract void f2297();
+    public abstract void f2298();
+    public abstract void f2299();
+    public abstract void f2300();
+    public abstract void f2301();
+    public abstract void f2302();
+    public abstract void f2303();
+    public abstract void f2304();
+    public abstract void f2305();
+    public abstract void f2306();
+    public abstract void f2307();
+    public abstract void f2308();
+    public abstract void f2309();
+    public abstract void f2310();
+    public abstract void f2311();
+    public abstract void f2312();
+    public abstract void f2313();
+    public abstract void f2314();
+    public abstract void f2315();
+    public abstract void f2316();
+    public abstract void f2317();
+    public abstract void f2318();
+    public abstract void f2319();
+    public abstract void f2320();
+    public abstract void f2321();
+    public abstract void f2322();
+    public abstract void f2323();
+    public abstract void f2324();
+    public abstract void f2325();
+    public abstract void f2326();
+    public abstract void f2327();
+    public abstract void f2328();
+    public abstract void f2329();
+    public abstract void f2330();
+    public abstract void f2331();
+    public abstract void f2332();
+    public abstract void f2333();
+    public abstract void f2334();
+    public abstract void f2335();
+    public abstract void f2336();
+    public abstract void f2337();
+    public abstract void f2338();
+    public abstract void f2339();
+    public abstract void f2340();
+    public abstract void f2341();
+    public abstract void f2342();
+    public abstract void f2343();
+    public abstract void f2344();
+    public abstract void f2345();
+    public abstract void f2346();
+    public abstract void f2347();
+    public abstract void f2348();
+    public abstract void f2349();
+    public abstract void f2350();
+    public abstract void f2351();
+    public abstract void f2352();
+    public abstract void f2353();
+    public abstract void f2354();
+    public abstract void f2355();
+    public abstract void f2356();
+    public abstract void f2357();
+    public abstract void f2358();
+    public abstract void f2359();
+    public abstract void f2360();
+    public abstract void f2361();
+    public abstract void f2362();
+    public abstract void f2363();
+    public abstract void f2364();
+    public abstract void f2365();
+    public abstract void f2366();
+    public abstract void f2367();
+    public abstract void f2368();
+    public abstract void f2369();
+    public abstract void f2370();
+    public abstract void f2371();
+    public abstract void f2372();
+    public abstract void f2373();
+    public abstract void f2374();
+    public abstract void f2375();
+    public abstract void f2376();
+    public abstract void f2377();
+    public abstract void f2378();
+    public abstract void f2379();
+    public abstract void f2380();
+    public abstract void f2381();
+    public abstract void f2382();
+    public abstract void f2383();
+    public abstract void f2384();
+    public abstract void f2385();
+    public abstract void f2386();
+    public abstract void f2387();
+    public abstract void f2388();
+    public abstract void f2389();
+    public abstract void f2390();
+    public abstract void f2391();
+    public abstract void f2392();
+    public abstract void f2393();
+    public abstract void f2394();
+    public abstract void f2395();
+    public abstract void f2396();
+    public abstract void f2397();
+    public abstract void f2398();
+    public abstract void f2399();
+    public abstract void f2400();
+    public abstract void f2401();
+    public abstract void f2402();
+    public abstract void f2403();
+    public abstract void f2404();
+    public abstract void f2405();
+    public abstract void f2406();
+    public abstract void f2407();
+    public abstract void f2408();
+    public abstract void f2409();
+    public abstract void f2410();
+    public abstract void f2411();
+    public abstract void f2412();
+    public abstract void f2413();
+    public abstract void f2414();
+    public abstract void f2415();
+    public abstract void f2416();
+    public abstract void f2417();
+    public abstract void f2418();
+    public abstract void f2419();
+    public abstract void f2420();
+    public abstract void f2421();
+    public abstract void f2422();
+    public abstract void f2423();
+    public abstract void f2424();
+    public abstract void f2425();
+    public abstract void f2426();
+    public abstract void f2427();
+    public abstract void f2428();
+    public abstract void f2429();
+    public abstract void f2430();
+    public abstract void f2431();
+    public abstract void f2432();
+    public abstract void f2433();
+    public abstract void f2434();
+    public abstract void f2435();
+    public abstract void f2436();
+    public abstract void f2437();
+    public abstract void f2438();
+    public abstract void f2439();
+    public abstract void f2440();
+    public abstract void f2441();
+    public abstract void f2442();
+    public abstract void f2443();
+    public abstract void f2444();
+    public abstract void f2445();
+    public abstract void f2446();
+    public abstract void f2447();
+    public abstract void f2448();
+    public abstract void f2449();
+    public abstract void f2450();
+    public abstract void f2451();
+    public abstract void f2452();
+    public abstract void f2453();
+    public abstract void f2454();
+    public abstract void f2455();
+    public abstract void f2456();
+    public abstract void f2457();
+    public abstract void f2458();
+    public abstract void f2459();
+    public abstract void f2460();
+    public abstract void f2461();
+    public abstract void f2462();
+    public abstract void f2463();
+    public abstract void f2464();
+    public abstract void f2465();
+    public abstract void f2466();
+    public abstract void f2467();
+    public abstract void f2468();
+    public abstract void f2469();
+    public abstract void f2470();
+    public abstract void f2471();
+    public abstract void f2472();
+    public abstract void f2473();
+    public abstract void f2474();
+    public abstract void f2475();
+    public abstract void f2476();
+    public abstract void f2477();
+    public abstract void f2478();
+    public abstract void f2479();
+    public abstract void f2480();
+    public abstract void f2481();
+    public abstract void f2482();
+    public abstract void f2483();
+    public abstract void f2484();
+    public abstract void f2485();
+    public abstract void f2486();
+    public abstract void f2487();
+    public abstract void f2488();
+    public abstract void f2489();
+    public abstract void f2490();
+    public abstract void f2491();
+    public abstract void f2492();
+    public abstract void f2493();
+    public abstract void f2494();
+    public abstract void f2495();
+    public abstract void f2496();
+    public abstract void f2497();
+    public abstract void f2498();
+    public abstract void f2499();
+    public abstract void f2500();
+    public abstract void f2501();
+    public abstract void f2502();
+    public abstract void f2503();
+    public abstract void f2504();
+    public abstract void f2505();
+    public abstract void f2506();
+    public abstract void f2507();
+    public abstract void f2508();
+    public abstract void f2509();
+    public abstract void f2510();
+    public abstract void f2511();
+    public abstract void f2512();
+    public abstract void f2513();
+    public abstract void f2514();
+    public abstract void f2515();
+    public abstract void f2516();
+    public abstract void f2517();
+    public abstract void f2518();
+    public abstract void f2519();
+    public abstract void f2520();
+    public abstract void f2521();
+    public abstract void f2522();
+    public abstract void f2523();
+    public abstract void f2524();
+    public abstract void f2525();
+    public abstract void f2526();
+    public abstract void f2527();
+    public abstract void f2528();
+    public abstract void f2529();
+    public abstract void f2530();
+    public abstract void f2531();
+    public abstract void f2532();
+    public abstract void f2533();
+    public abstract void f2534();
+    public abstract void f2535();
+    public abstract void f2536();
+    public abstract void f2537();
+    public abstract void f2538();
+    public abstract void f2539();
+    public abstract void f2540();
+    public abstract void f2541();
+    public abstract void f2542();
+    public abstract void f2543();
+    public abstract void f2544();
+    public abstract void f2545();
+    public abstract void f2546();
+    public abstract void f2547();
+    public abstract void f2548();
+    public abstract void f2549();
+    public abstract void f2550();
+    public abstract void f2551();
+    public abstract void f2552();
+    public abstract void f2553();
+    public abstract void f2554();
+    public abstract void f2555();
+    public abstract void f2556();
+    public abstract void f2557();
+    public abstract void f2558();
+    public abstract void f2559();
+    public abstract void f2560();
+    public abstract void f2561();
+    public abstract void f2562();
+    public abstract void f2563();
+    public abstract void f2564();
+    public abstract void f2565();
+    public abstract void f2566();
+    public abstract void f2567();
+    public abstract void f2568();
+    public abstract void f2569();
+    public abstract void f2570();
+    public abstract void f2571();
+    public abstract void f2572();
+    public abstract void f2573();
+    public abstract void f2574();
+    public abstract void f2575();
+    public abstract void f2576();
+    public abstract void f2577();
+    public abstract void f2578();
+    public abstract void f2579();
+    public abstract void f2580();
+    public abstract void f2581();
+    public abstract void f2582();
+    public abstract void f2583();
+    public abstract void f2584();
+    public abstract void f2585();
+    public abstract void f2586();
+    public abstract void f2587();
+    public abstract void f2588();
+    public abstract void f2589();
+    public abstract void f2590();
+    public abstract void f2591();
+    public abstract void f2592();
+    public abstract void f2593();
+    public abstract void f2594();
+    public abstract void f2595();
+    public abstract void f2596();
+    public abstract void f2597();
+    public abstract void f2598();
+    public abstract void f2599();
+    public abstract void f2600();
+    public abstract void f2601();
+    public abstract void f2602();
+    public abstract void f2603();
+    public abstract void f2604();
+    public abstract void f2605();
+    public abstract void f2606();
+    public abstract void f2607();
+    public abstract void f2608();
+    public abstract void f2609();
+    public abstract void f2610();
+    public abstract void f2611();
+    public abstract void f2612();
+    public abstract void f2613();
+    public abstract void f2614();
+    public abstract void f2615();
+    public abstract void f2616();
+    public abstract void f2617();
+    public abstract void f2618();
+    public abstract void f2619();
+    public abstract void f2620();
+    public abstract void f2621();
+    public abstract void f2622();
+    public abstract void f2623();
+    public abstract void f2624();
+    public abstract void f2625();
+    public abstract void f2626();
+    public abstract void f2627();
+    public abstract void f2628();
+    public abstract void f2629();
+    public abstract void f2630();
+    public abstract void f2631();
+    public abstract void f2632();
+    public abstract void f2633();
+    public abstract void f2634();
+    public abstract void f2635();
+    public abstract void f2636();
+    public abstract void f2637();
+    public abstract void f2638();
+    public abstract void f2639();
+    public abstract void f2640();
+    public abstract void f2641();
+    public abstract void f2642();
+    public abstract void f2643();
+    public abstract void f2644();
+    public abstract void f2645();
+    public abstract void f2646();
+    public abstract void f2647();
+    public abstract void f2648();
+    public abstract void f2649();
+    public abstract void f2650();
+    public abstract void f2651();
+    public abstract void f2652();
+    public abstract void f2653();
+    public abstract void f2654();
+    public abstract void f2655();
+    public abstract void f2656();
+    public abstract void f2657();
+    public abstract void f2658();
+    public abstract void f2659();
+    public abstract void f2660();
+    public abstract void f2661();
+    public abstract void f2662();
+    public abstract void f2663();
+    public abstract void f2664();
+    public abstract void f2665();
+    public abstract void f2666();
+    public abstract void f2667();
+    public abstract void f2668();
+    public abstract void f2669();
+    public abstract void f2670();
+    public abstract void f2671();
+    public abstract void f2672();
+    public abstract void f2673();
+    public abstract void f2674();
+    public abstract void f2675();
+    public abstract void f2676();
+    public abstract void f2677();
+    public abstract void f2678();
+    public abstract void f2679();
+    public abstract void f2680();
+    public abstract void f2681();
+    public abstract void f2682();
+    public abstract void f2683();
+    public abstract void f2684();
+    public abstract void f2685();
+    public abstract void f2686();
+    public abstract void f2687();
+    public abstract void f2688();
+    public abstract void f2689();
+    public abstract void f2690();
+    public abstract void f2691();
+    public abstract void f2692();
+    public abstract void f2693();
+    public abstract void f2694();
+    public abstract void f2695();
+    public abstract void f2696();
+    public abstract void f2697();
+    public abstract void f2698();
+    public abstract void f2699();
+    public abstract void f2700();
+    public abstract void f2701();
+    public abstract void f2702();
+    public abstract void f2703();
+    public abstract void f2704();
+    public abstract void f2705();
+    public abstract void f2706();
+    public abstract void f2707();
+    public abstract void f2708();
+    public abstract void f2709();
+    public abstract void f2710();
+    public abstract void f2711();
+    public abstract void f2712();
+    public abstract void f2713();
+    public abstract void f2714();
+    public abstract void f2715();
+    public abstract void f2716();
+    public abstract void f2717();
+    public abstract void f2718();
+    public abstract void f2719();
+    public abstract void f2720();
+    public abstract void f2721();
+    public abstract void f2722();
+    public abstract void f2723();
+    public abstract void f2724();
+    public abstract void f2725();
+    public abstract void f2726();
+    public abstract void f2727();
+    public abstract void f2728();
+    public abstract void f2729();
+    public abstract void f2730();
+    public abstract void f2731();
+    public abstract void f2732();
+    public abstract void f2733();
+    public abstract void f2734();
+    public abstract void f2735();
+    public abstract void f2736();
+    public abstract void f2737();
+    public abstract void f2738();
+    public abstract void f2739();
+    public abstract void f2740();
+    public abstract void f2741();
+    public abstract void f2742();
+    public abstract void f2743();
+    public abstract void f2744();
+    public abstract void f2745();
+    public abstract void f2746();
+    public abstract void f2747();
+    public abstract void f2748();
+    public abstract void f2749();
+    public abstract void f2750();
+    public abstract void f2751();
+    public abstract void f2752();
+    public abstract void f2753();
+    public abstract void f2754();
+    public abstract void f2755();
+    public abstract void f2756();
+    public abstract void f2757();
+    public abstract void f2758();
+    public abstract void f2759();
+    public abstract void f2760();
+    public abstract void f2761();
+    public abstract void f2762();
+    public abstract void f2763();
+    public abstract void f2764();
+    public abstract void f2765();
+    public abstract void f2766();
+    public abstract void f2767();
+    public abstract void f2768();
+    public abstract void f2769();
+    public abstract void f2770();
+    public abstract void f2771();
+    public abstract void f2772();
+    public abstract void f2773();
+    public abstract void f2774();
+    public abstract void f2775();
+    public abstract void f2776();
+    public abstract void f2777();
+    public abstract void f2778();
+    public abstract void f2779();
+    public abstract void f2780();
+    public abstract void f2781();
+    public abstract void f2782();
+    public abstract void f2783();
+    public abstract void f2784();
+    public abstract void f2785();
+    public abstract void f2786();
+    public abstract void f2787();
+    public abstract void f2788();
+    public abstract void f2789();
+    public abstract void f2790();
+    public abstract void f2791();
+    public abstract void f2792();
+    public abstract void f2793();
+    public abstract void f2794();
+    public abstract void f2795();
+    public abstract void f2796();
+    public abstract void f2797();
+    public abstract void f2798();
+    public abstract void f2799();
+    public abstract void f2800();
+    public abstract void f2801();
+    public abstract void f2802();
+    public abstract void f2803();
+    public abstract void f2804();
+    public abstract void f2805();
+    public abstract void f2806();
+    public abstract void f2807();
+    public abstract void f2808();
+    public abstract void f2809();
+    public abstract void f2810();
+    public abstract void f2811();
+    public abstract void f2812();
+    public abstract void f2813();
+    public abstract void f2814();
+    public abstract void f2815();
+    public abstract void f2816();
+    public abstract void f2817();
+    public abstract void f2818();
+    public abstract void f2819();
+    public abstract void f2820();
+    public abstract void f2821();
+    public abstract void f2822();
+    public abstract void f2823();
+    public abstract void f2824();
+    public abstract void f2825();
+    public abstract void f2826();
+    public abstract void f2827();
+    public abstract void f2828();
+    public abstract void f2829();
+    public abstract void f2830();
+    public abstract void f2831();
+    public abstract void f2832();
+    public abstract void f2833();
+    public abstract void f2834();
+    public abstract void f2835();
+    public abstract void f2836();
+    public abstract void f2837();
+    public abstract void f2838();
+    public abstract void f2839();
+    public abstract void f2840();
+    public abstract void f2841();
+    public abstract void f2842();
+    public abstract void f2843();
+    public abstract void f2844();
+    public abstract void f2845();
+    public abstract void f2846();
+    public abstract void f2847();
+    public abstract void f2848();
+    public abstract void f2849();
+    public abstract void f2850();
+    public abstract void f2851();
+    public abstract void f2852();
+    public abstract void f2853();
+    public abstract void f2854();
+    public abstract void f2855();
+    public abstract void f2856();
+    public abstract void f2857();
+    public abstract void f2858();
+    public abstract void f2859();
+    public abstract void f2860();
+    public abstract void f2861();
+    public abstract void f2862();
+    public abstract void f2863();
+    public abstract void f2864();
+    public abstract void f2865();
+    public abstract void f2866();
+    public abstract void f2867();
+    public abstract void f2868();
+    public abstract void f2869();
+    public abstract void f2870();
+    public abstract void f2871();
+    public abstract void f2872();
+    public abstract void f2873();
+    public abstract void f2874();
+    public abstract void f2875();
+    public abstract void f2876();
+    public abstract void f2877();
+    public abstract void f2878();
+    public abstract void f2879();
+    public abstract void f2880();
+    public abstract void f2881();
+    public abstract void f2882();
+    public abstract void f2883();
+    public abstract void f2884();
+    public abstract void f2885();
+    public abstract void f2886();
+    public abstract void f2887();
+    public abstract void f2888();
+    public abstract void f2889();
+    public abstract void f2890();
+    public abstract void f2891();
+    public abstract void f2892();
+    public abstract void f2893();
+    public abstract void f2894();
+    public abstract void f2895();
+    public abstract void f2896();
+    public abstract void f2897();
+    public abstract void f2898();
+    public abstract void f2899();
+    public abstract void f2900();
+    public abstract void f2901();
+    public abstract void f2902();
+    public abstract void f2903();
+    public abstract void f2904();
+    public abstract void f2905();
+    public abstract void f2906();
+    public abstract void f2907();
+    public abstract void f2908();
+    public abstract void f2909();
+    public abstract void f2910();
+    public abstract void f2911();
+    public abstract void f2912();
+    public abstract void f2913();
+    public abstract void f2914();
+    public abstract void f2915();
+    public abstract void f2916();
+    public abstract void f2917();
+    public abstract void f2918();
+    public abstract void f2919();
+    public abstract void f2920();
+    public abstract void f2921();
+    public abstract void f2922();
+    public abstract void f2923();
+    public abstract void f2924();
+    public abstract void f2925();
+    public abstract void f2926();
+    public abstract void f2927();
+    public abstract void f2928();
+    public abstract void f2929();
+    public abstract void f2930();
+    public abstract void f2931();
+    public abstract void f2932();
+    public abstract void f2933();
+    public abstract void f2934();
+    public abstract void f2935();
+    public abstract void f2936();
+    public abstract void f2937();
+    public abstract void f2938();
+    public abstract void f2939();
+    public abstract void f2940();
+    public abstract void f2941();
+    public abstract void f2942();
+    public abstract void f2943();
+    public abstract void f2944();
+    public abstract void f2945();
+    public abstract void f2946();
+    public abstract void f2947();
+    public abstract void f2948();
+    public abstract void f2949();
+    public abstract void f2950();
+    public abstract void f2951();
+    public abstract void f2952();
+    public abstract void f2953();
+    public abstract void f2954();
+    public abstract void f2955();
+    public abstract void f2956();
+    public abstract void f2957();
+    public abstract void f2958();
+    public abstract void f2959();
+    public abstract void f2960();
+    public abstract void f2961();
+    public abstract void f2962();
+    public abstract void f2963();
+    public abstract void f2964();
+    public abstract void f2965();
+    public abstract void f2966();
+    public abstract void f2967();
+    public abstract void f2968();
+    public abstract void f2969();
+    public abstract void f2970();
+    public abstract void f2971();
+    public abstract void f2972();
+    public abstract void f2973();
+    public abstract void f2974();
+    public abstract void f2975();
+    public abstract void f2976();
+    public abstract void f2977();
+    public abstract void f2978();
+    public abstract void f2979();
+    public abstract void f2980();
+    public abstract void f2981();
+    public abstract void f2982();
+    public abstract void f2983();
+    public abstract void f2984();
+    public abstract void f2985();
+    public abstract void f2986();
+    public abstract void f2987();
+    public abstract void f2988();
+    public abstract void f2989();
+    public abstract void f2990();
+    public abstract void f2991();
+    public abstract void f2992();
+    public abstract void f2993();
+    public abstract void f2994();
+    public abstract void f2995();
+    public abstract void f2996();
+    public abstract void f2997();
+    public abstract void f2998();
+    public abstract void f2999();
+    public abstract void f3000();
+    public abstract void f3001();
+    public abstract void f3002();
+    public abstract void f3003();
+    public abstract void f3004();
+    public abstract void f3005();
+    public abstract void f3006();
+    public abstract void f3007();
+    public abstract void f3008();
+    public abstract void f3009();
+    public abstract void f3010();
+    public abstract void f3011();
+    public abstract void f3012();
+    public abstract void f3013();
+    public abstract void f3014();
+    public abstract void f3015();
+    public abstract void f3016();
+    public abstract void f3017();
+    public abstract void f3018();
+    public abstract void f3019();
+    public abstract void f3020();
+    public abstract void f3021();
+    public abstract void f3022();
+    public abstract void f3023();
+    public abstract void f3024();
+    public abstract void f3025();
+    public abstract void f3026();
+    public abstract void f3027();
+    public abstract void f3028();
+    public abstract void f3029();
+    public abstract void f3030();
+    public abstract void f3031();
+    public abstract void f3032();
+    public abstract void f3033();
+    public abstract void f3034();
+    public abstract void f3035();
+    public abstract void f3036();
+    public abstract void f3037();
+    public abstract void f3038();
+    public abstract void f3039();
+    public abstract void f3040();
+    public abstract void f3041();
+    public abstract void f3042();
+    public abstract void f3043();
+    public abstract void f3044();
+    public abstract void f3045();
+    public abstract void f3046();
+    public abstract void f3047();
+    public abstract void f3048();
+    public abstract void f3049();
+    public abstract void f3050();
+    public abstract void f3051();
+    public abstract void f3052();
+    public abstract void f3053();
+    public abstract void f3054();
+    public abstract void f3055();
+    public abstract void f3056();
+    public abstract void f3057();
+    public abstract void f3058();
+    public abstract void f3059();
+    public abstract void f3060();
+    public abstract void f3061();
+    public abstract void f3062();
+    public abstract void f3063();
+    public abstract void f3064();
+    public abstract void f3065();
+    public abstract void f3066();
+    public abstract void f3067();
+    public abstract void f3068();
+    public abstract void f3069();
+    public abstract void f3070();
+    public abstract void f3071();
+    public abstract void f3072();
+    public abstract void f3073();
+    public abstract void f3074();
+    public abstract void f3075();
+    public abstract void f3076();
+    public abstract void f3077();
+    public abstract void f3078();
+    public abstract void f3079();
+    public abstract void f3080();
+    public abstract void f3081();
+    public abstract void f3082();
+    public abstract void f3083();
+    public abstract void f3084();
+    public abstract void f3085();
+    public abstract void f3086();
+    public abstract void f3087();
+    public abstract void f3088();
+    public abstract void f3089();
+    public abstract void f3090();
+    public abstract void f3091();
+    public abstract void f3092();
+    public abstract void f3093();
+    public abstract void f3094();
+    public abstract void f3095();
+    public abstract void f3096();
+    public abstract void f3097();
+    public abstract void f3098();
+    public abstract void f3099();
+    public abstract void f3100();
+    public abstract void f3101();
+    public abstract void f3102();
+    public abstract void f3103();
+    public abstract void f3104();
+    public abstract void f3105();
+    public abstract void f3106();
+    public abstract void f3107();
+    public abstract void f3108();
+    public abstract void f3109();
+    public abstract void f3110();
+    public abstract void f3111();
+    public abstract void f3112();
+    public abstract void f3113();
+    public abstract void f3114();
+    public abstract void f3115();
+    public abstract void f3116();
+    public abstract void f3117();
+    public abstract void f3118();
+    public abstract void f3119();
+    public abstract void f3120();
+    public abstract void f3121();
+    public abstract void f3122();
+    public abstract void f3123();
+    public abstract void f3124();
+    public abstract void f3125();
+    public abstract void f3126();
+    public abstract void f3127();
+    public abstract void f3128();
+    public abstract void f3129();
+    public abstract void f3130();
+    public abstract void f3131();
+    public abstract void f3132();
+    public abstract void f3133();
+    public abstract void f3134();
+    public abstract void f3135();
+    public abstract void f3136();
+    public abstract void f3137();
+    public abstract void f3138();
+    public abstract void f3139();
+    public abstract void f3140();
+    public abstract void f3141();
+    public abstract void f3142();
+    public abstract void f3143();
+    public abstract void f3144();
+    public abstract void f3145();
+    public abstract void f3146();
+    public abstract void f3147();
+    public abstract void f3148();
+    public abstract void f3149();
+    public abstract void f3150();
+    public abstract void f3151();
+    public abstract void f3152();
+    public abstract void f3153();
+    public abstract void f3154();
+    public abstract void f3155();
+    public abstract void f3156();
+    public abstract void f3157();
+    public abstract void f3158();
+    public abstract void f3159();
+    public abstract void f3160();
+    public abstract void f3161();
+    public abstract void f3162();
+    public abstract void f3163();
+    public abstract void f3164();
+    public abstract void f3165();
+    public abstract void f3166();
+    public abstract void f3167();
+    public abstract void f3168();
+    public abstract void f3169();
+    public abstract void f3170();
+    public abstract void f3171();
+    public abstract void f3172();
+    public abstract void f3173();
+    public abstract void f3174();
+    public abstract void f3175();
+    public abstract void f3176();
+    public abstract void f3177();
+    public abstract void f3178();
+    public abstract void f3179();
+    public abstract void f3180();
+    public abstract void f3181();
+    public abstract void f3182();
+    public abstract void f3183();
+    public abstract void f3184();
+    public abstract void f3185();
+    public abstract void f3186();
+    public abstract void f3187();
+    public abstract void f3188();
+    public abstract void f3189();
+    public abstract void f3190();
+    public abstract void f3191();
+    public abstract void f3192();
+    public abstract void f3193();
+    public abstract void f3194();
+    public abstract void f3195();
+    public abstract void f3196();
+    public abstract void f3197();
+    public abstract void f3198();
+    public abstract void f3199();
+    public abstract void f3200();
+    public abstract void f3201();
+    public abstract void f3202();
+    public abstract void f3203();
+    public abstract void f3204();
+    public abstract void f3205();
+    public abstract void f3206();
+    public abstract void f3207();
+    public abstract void f3208();
+    public abstract void f3209();
+    public abstract void f3210();
+    public abstract void f3211();
+    public abstract void f3212();
+    public abstract void f3213();
+    public abstract void f3214();
+    public abstract void f3215();
+    public abstract void f3216();
+    public abstract void f3217();
+    public abstract void f3218();
+    public abstract void f3219();
+    public abstract void f3220();
+    public abstract void f3221();
+    public abstract void f3222();
+    public abstract void f3223();
+    public abstract void f3224();
+    public abstract void f3225();
+    public abstract void f3226();
+    public abstract void f3227();
+    public abstract void f3228();
+    public abstract void f3229();
+    public abstract void f3230();
+    public abstract void f3231();
+    public abstract void f3232();
+    public abstract void f3233();
+    public abstract void f3234();
+    public abstract void f3235();
+    public abstract void f3236();
+    public abstract void f3237();
+    public abstract void f3238();
+    public abstract void f3239();
+    public abstract void f3240();
+    public abstract void f3241();
+    public abstract void f3242();
+    public abstract void f3243();
+    public abstract void f3244();
+    public abstract void f3245();
+    public abstract void f3246();
+    public abstract void f3247();
+    public abstract void f3248();
+    public abstract void f3249();
+    public abstract void f3250();
+    public abstract void f3251();
+    public abstract void f3252();
+    public abstract void f3253();
+    public abstract void f3254();
+    public abstract void f3255();
+    public abstract void f3256();
+    public abstract void f3257();
+    public abstract void f3258();
+    public abstract void f3259();
+    public abstract void f3260();
+    public abstract void f3261();
+    public abstract void f3262();
+    public abstract void f3263();
+    public abstract void f3264();
+    public abstract void f3265();
+    public abstract void f3266();
+    public abstract void f3267();
+    public abstract void f3268();
+    public abstract void f3269();
+    public abstract void f3270();
+    public abstract void f3271();
+    public abstract void f3272();
+    public abstract void f3273();
+    public abstract void f3274();
+    public abstract void f3275();
+    public abstract void f3276();
+    public abstract void f3277();
+    public abstract void f3278();
+    public abstract void f3279();
+    public abstract void f3280();
+    public abstract void f3281();
+    public abstract void f3282();
+    public abstract void f3283();
+    public abstract void f3284();
+    public abstract void f3285();
+    public abstract void f3286();
+    public abstract void f3287();
+    public abstract void f3288();
+    public abstract void f3289();
+    public abstract void f3290();
+    public abstract void f3291();
+    public abstract void f3292();
+    public abstract void f3293();
+    public abstract void f3294();
+    public abstract void f3295();
+    public abstract void f3296();
+    public abstract void f3297();
+    public abstract void f3298();
+    public abstract void f3299();
+    public abstract void f3300();
+    public abstract void f3301();
+    public abstract void f3302();
+    public abstract void f3303();
+    public abstract void f3304();
+    public abstract void f3305();
+    public abstract void f3306();
+    public abstract void f3307();
+    public abstract void f3308();
+    public abstract void f3309();
+    public abstract void f3310();
+    public abstract void f3311();
+    public abstract void f3312();
+    public abstract void f3313();
+    public abstract void f3314();
+    public abstract void f3315();
+    public abstract void f3316();
+    public abstract void f3317();
+    public abstract void f3318();
+    public abstract void f3319();
+    public abstract void f3320();
+    public abstract void f3321();
+    public abstract void f3322();
+    public abstract void f3323();
+    public abstract void f3324();
+    public abstract void f3325();
+    public abstract void f3326();
+    public abstract void f3327();
+    public abstract void f3328();
+    public abstract void f3329();
+    public abstract void f3330();
+    public abstract void f3331();
+    public abstract void f3332();
+    public abstract void f3333();
+    public abstract void f3334();
+    public abstract void f3335();
+    public abstract void f3336();
+    public abstract void f3337();
+    public abstract void f3338();
+    public abstract void f3339();
+    public abstract void f3340();
+    public abstract void f3341();
+    public abstract void f3342();
+    public abstract void f3343();
+    public abstract void f3344();
+    public abstract void f3345();
+    public abstract void f3346();
+    public abstract void f3347();
+    public abstract void f3348();
+    public abstract void f3349();
+    public abstract void f3350();
+    public abstract void f3351();
+    public abstract void f3352();
+    public abstract void f3353();
+    public abstract void f3354();
+    public abstract void f3355();
+    public abstract void f3356();
+    public abstract void f3357();
+    public abstract void f3358();
+    public abstract void f3359();
+    public abstract void f3360();
+    public abstract void f3361();
+    public abstract void f3362();
+    public abstract void f3363();
+    public abstract void f3364();
+    public abstract void f3365();
+    public abstract void f3366();
+    public abstract void f3367();
+    public abstract void f3368();
+    public abstract void f3369();
+    public abstract void f3370();
+    public abstract void f3371();
+    public abstract void f3372();
+    public abstract void f3373();
+    public abstract void f3374();
+    public abstract void f3375();
+    public abstract void f3376();
+    public abstract void f3377();
+    public abstract void f3378();
+    public abstract void f3379();
+    public abstract void f3380();
+    public abstract void f3381();
+    public abstract void f3382();
+    public abstract void f3383();
+    public abstract void f3384();
+    public abstract void f3385();
+    public abstract void f3386();
+    public abstract void f3387();
+    public abstract void f3388();
+    public abstract void f3389();
+    public abstract void f3390();
+    public abstract void f3391();
+    public abstract void f3392();
+    public abstract void f3393();
+    public abstract void f3394();
+    public abstract void f3395();
+    public abstract void f3396();
+    public abstract void f3397();
+    public abstract void f3398();
+    public abstract void f3399();
+    public abstract void f3400();
+    public abstract void f3401();
+    public abstract void f3402();
+    public abstract void f3403();
+    public abstract void f3404();
+    public abstract void f3405();
+    public abstract void f3406();
+    public abstract void f3407();
+    public abstract void f3408();
+    public abstract void f3409();
+    public abstract void f3410();
+    public abstract void f3411();
+    public abstract void f3412();
+    public abstract void f3413();
+    public abstract void f3414();
+    public abstract void f3415();
+    public abstract void f3416();
+    public abstract void f3417();
+    public abstract void f3418();
+    public abstract void f3419();
+    public abstract void f3420();
+    public abstract void f3421();
+    public abstract void f3422();
+    public abstract void f3423();
+    public abstract void f3424();
+    public abstract void f3425();
+    public abstract void f3426();
+    public abstract void f3427();
+    public abstract void f3428();
+    public abstract void f3429();
+    public abstract void f3430();
+    public abstract void f3431();
+    public abstract void f3432();
+    public abstract void f3433();
+    public abstract void f3434();
+    public abstract void f3435();
+    public abstract void f3436();
+    public abstract void f3437();
+    public abstract void f3438();
+    public abstract void f3439();
+    public abstract void f3440();
+    public abstract void f3441();
+    public abstract void f3442();
+    public abstract void f3443();
+    public abstract void f3444();
+    public abstract void f3445();
+    public abstract void f3446();
+    public abstract void f3447();
+    public abstract void f3448();
+    public abstract void f3449();
+    public abstract void f3450();
+    public abstract void f3451();
+    public abstract void f3452();
+    public abstract void f3453();
+    public abstract void f3454();
+    public abstract void f3455();
+    public abstract void f3456();
+    public abstract void f3457();
+    public abstract void f3458();
+    public abstract void f3459();
+    public abstract void f3460();
+    public abstract void f3461();
+    public abstract void f3462();
+    public abstract void f3463();
+    public abstract void f3464();
+    public abstract void f3465();
+    public abstract void f3466();
+    public abstract void f3467();
+    public abstract void f3468();
+    public abstract void f3469();
+    public abstract void f3470();
+    public abstract void f3471();
+    public abstract void f3472();
+    public abstract void f3473();
+    public abstract void f3474();
+    public abstract void f3475();
+    public abstract void f3476();
+    public abstract void f3477();
+    public abstract void f3478();
+    public abstract void f3479();
+    public abstract void f3480();
+    public abstract void f3481();
+    public abstract void f3482();
+    public abstract void f3483();
+    public abstract void f3484();
+    public abstract void f3485();
+    public abstract void f3486();
+    public abstract void f3487();
+    public abstract void f3488();
+    public abstract void f3489();
+    public abstract void f3490();
+    public abstract void f3491();
+    public abstract void f3492();
+    public abstract void f3493();
+    public abstract void f3494();
+    public abstract void f3495();
+    public abstract void f3496();
+    public abstract void f3497();
+    public abstract void f3498();
+    public abstract void f3499();
+    public abstract void f3500();
+    public abstract void f3501();
+    public abstract void f3502();
+    public abstract void f3503();
+    public abstract void f3504();
+    public abstract void f3505();
+    public abstract void f3506();
+    public abstract void f3507();
+    public abstract void f3508();
+    public abstract void f3509();
+    public abstract void f3510();
+    public abstract void f3511();
+    public abstract void f3512();
+    public abstract void f3513();
+    public abstract void f3514();
+    public abstract void f3515();
+    public abstract void f3516();
+    public abstract void f3517();
+    public abstract void f3518();
+    public abstract void f3519();
+    public abstract void f3520();
+    public abstract void f3521();
+    public abstract void f3522();
+    public abstract void f3523();
+    public abstract void f3524();
+    public abstract void f3525();
+    public abstract void f3526();
+    public abstract void f3527();
+    public abstract void f3528();
+    public abstract void f3529();
+    public abstract void f3530();
+    public abstract void f3531();
+    public abstract void f3532();
+    public abstract void f3533();
+    public abstract void f3534();
+    public abstract void f3535();
+    public abstract void f3536();
+    public abstract void f3537();
+    public abstract void f3538();
+    public abstract void f3539();
+    public abstract void f3540();
+    public abstract void f3541();
+    public abstract void f3542();
+    public abstract void f3543();
+    public abstract void f3544();
+    public abstract void f3545();
+    public abstract void f3546();
+    public abstract void f3547();
+    public abstract void f3548();
+    public abstract void f3549();
+    public abstract void f3550();
+    public abstract void f3551();
+    public abstract void f3552();
+    public abstract void f3553();
+    public abstract void f3554();
+    public abstract void f3555();
+    public abstract void f3556();
+    public abstract void f3557();
+    public abstract void f3558();
+    public abstract void f3559();
+    public abstract void f3560();
+    public abstract void f3561();
+    public abstract void f3562();
+    public abstract void f3563();
+    public abstract void f3564();
+    public abstract void f3565();
+    public abstract void f3566();
+    public abstract void f3567();
+    public abstract void f3568();
+    public abstract void f3569();
+    public abstract void f3570();
+    public abstract void f3571();
+    public abstract void f3572();
+    public abstract void f3573();
+    public abstract void f3574();
+    public abstract void f3575();
+    public abstract void f3576();
+    public abstract void f3577();
+    public abstract void f3578();
+    public abstract void f3579();
+    public abstract void f3580();
+    public abstract void f3581();
+    public abstract void f3582();
+    public abstract void f3583();
+    public abstract void f3584();
+    public abstract void f3585();
+    public abstract void f3586();
+    public abstract void f3587();
+    public abstract void f3588();
+    public abstract void f3589();
+    public abstract void f3590();
+    public abstract void f3591();
+    public abstract void f3592();
+    public abstract void f3593();
+    public abstract void f3594();
+    public abstract void f3595();
+    public abstract void f3596();
+    public abstract void f3597();
+    public abstract void f3598();
+    public abstract void f3599();
+    public abstract void f3600();
+    public abstract void f3601();
+    public abstract void f3602();
+    public abstract void f3603();
+    public abstract void f3604();
+    public abstract void f3605();
+    public abstract void f3606();
+    public abstract void f3607();
+    public abstract void f3608();
+    public abstract void f3609();
+    public abstract void f3610();
+    public abstract void f3611();
+    public abstract void f3612();
+    public abstract void f3613();
+    public abstract void f3614();
+    public abstract void f3615();
+    public abstract void f3616();
+    public abstract void f3617();
+    public abstract void f3618();
+    public abstract void f3619();
+    public abstract void f3620();
+    public abstract void f3621();
+    public abstract void f3622();
+    public abstract void f3623();
+    public abstract void f3624();
+    public abstract void f3625();
+    public abstract void f3626();
+    public abstract void f3627();
+    public abstract void f3628();
+    public abstract void f3629();
+    public abstract void f3630();
+    public abstract void f3631();
+    public abstract void f3632();
+    public abstract void f3633();
+    public abstract void f3634();
+    public abstract void f3635();
+    public abstract void f3636();
+    public abstract void f3637();
+    public abstract void f3638();
+    public abstract void f3639();
+    public abstract void f3640();
+    public abstract void f3641();
+    public abstract void f3642();
+    public abstract void f3643();
+    public abstract void f3644();
+    public abstract void f3645();
+    public abstract void f3646();
+    public abstract void f3647();
+    public abstract void f3648();
+    public abstract void f3649();
+    public abstract void f3650();
+    public abstract void f3651();
+    public abstract void f3652();
+    public abstract void f3653();
+    public abstract void f3654();
+    public abstract void f3655();
+    public abstract void f3656();
+    public abstract void f3657();
+    public abstract void f3658();
+    public abstract void f3659();
+    public abstract void f3660();
+    public abstract void f3661();
+    public abstract void f3662();
+    public abstract void f3663();
+    public abstract void f3664();
+    public abstract void f3665();
+    public abstract void f3666();
+    public abstract void f3667();
+    public abstract void f3668();
+    public abstract void f3669();
+    public abstract void f3670();
+    public abstract void f3671();
+    public abstract void f3672();
+    public abstract void f3673();
+    public abstract void f3674();
+    public abstract void f3675();
+    public abstract void f3676();
+    public abstract void f3677();
+    public abstract void f3678();
+    public abstract void f3679();
+    public abstract void f3680();
+    public abstract void f3681();
+    public abstract void f3682();
+    public abstract void f3683();
+    public abstract void f3684();
+    public abstract void f3685();
+    public abstract void f3686();
+    public abstract void f3687();
+    public abstract void f3688();
+    public abstract void f3689();
+    public abstract void f3690();
+    public abstract void f3691();
+    public abstract void f3692();
+    public abstract void f3693();
+    public abstract void f3694();
+    public abstract void f3695();
+    public abstract void f3696();
+    public abstract void f3697();
+    public abstract void f3698();
+    public abstract void f3699();
+    public abstract void f3700();
+    public abstract void f3701();
+    public abstract void f3702();
+    public abstract void f3703();
+    public abstract void f3704();
+    public abstract void f3705();
+    public abstract void f3706();
+    public abstract void f3707();
+    public abstract void f3708();
+    public abstract void f3709();
+    public abstract void f3710();
+    public abstract void f3711();
+    public abstract void f3712();
+    public abstract void f3713();
+    public abstract void f3714();
+    public abstract void f3715();
+    public abstract void f3716();
+    public abstract void f3717();
+    public abstract void f3718();
+    public abstract void f3719();
+    public abstract void f3720();
+    public abstract void f3721();
+    public abstract void f3722();
+    public abstract void f3723();
+    public abstract void f3724();
+    public abstract void f3725();
+    public abstract void f3726();
+    public abstract void f3727();
+    public abstract void f3728();
+    public abstract void f3729();
+    public abstract void f3730();
+    public abstract void f3731();
+    public abstract void f3732();
+    public abstract void f3733();
+    public abstract void f3734();
+    public abstract void f3735();
+    public abstract void f3736();
+    public abstract void f3737();
+    public abstract void f3738();
+    public abstract void f3739();
+    public abstract void f3740();
+    public abstract void f3741();
+    public abstract void f3742();
+    public abstract void f3743();
+    public abstract void f3744();
+    public abstract void f3745();
+    public abstract void f3746();
+    public abstract void f3747();
+    public abstract void f3748();
+    public abstract void f3749();
+    public abstract void f3750();
+    public abstract void f3751();
+    public abstract void f3752();
+    public abstract void f3753();
+    public abstract void f3754();
+    public abstract void f3755();
+    public abstract void f3756();
+    public abstract void f3757();
+    public abstract void f3758();
+    public abstract void f3759();
+    public abstract void f3760();
+    public abstract void f3761();
+    public abstract void f3762();
+    public abstract void f3763();
+    public abstract void f3764();
+    public abstract void f3765();
+    public abstract void f3766();
+    public abstract void f3767();
+    public abstract void f3768();
+    public abstract void f3769();
+    public abstract void f3770();
+    public abstract void f3771();
+    public abstract void f3772();
+    public abstract void f3773();
+    public abstract void f3774();
+    public abstract void f3775();
+    public abstract void f3776();
+    public abstract void f3777();
+    public abstract void f3778();
+    public abstract void f3779();
+    public abstract void f3780();
+    public abstract void f3781();
+    public abstract void f3782();
+    public abstract void f3783();
+    public abstract void f3784();
+    public abstract void f3785();
+    public abstract void f3786();
+    public abstract void f3787();
+    public abstract void f3788();
+    public abstract void f3789();
+    public abstract void f3790();
+    public abstract void f3791();
+    public abstract void f3792();
+    public abstract void f3793();
+    public abstract void f3794();
+    public abstract void f3795();
+    public abstract void f3796();
+    public abstract void f3797();
+    public abstract void f3798();
+    public abstract void f3799();
+    public abstract void f3800();
+    public abstract void f3801();
+    public abstract void f3802();
+    public abstract void f3803();
+    public abstract void f3804();
+    public abstract void f3805();
+    public abstract void f3806();
+    public abstract void f3807();
+    public abstract void f3808();
+    public abstract void f3809();
+    public abstract void f3810();
+    public abstract void f3811();
+    public abstract void f3812();
+    public abstract void f3813();
+    public abstract void f3814();
+    public abstract void f3815();
+    public abstract void f3816();
+    public abstract void f3817();
+    public abstract void f3818();
+    public abstract void f3819();
+    public abstract void f3820();
+    public abstract void f3821();
+    public abstract void f3822();
+    public abstract void f3823();
+    public abstract void f3824();
+    public abstract void f3825();
+    public abstract void f3826();
+    public abstract void f3827();
+    public abstract void f3828();
+    public abstract void f3829();
+    public abstract void f3830();
+    public abstract void f3831();
+    public abstract void f3832();
+    public abstract void f3833();
+    public abstract void f3834();
+    public abstract void f3835();
+    public abstract void f3836();
+    public abstract void f3837();
+    public abstract void f3838();
+    public abstract void f3839();
+    public abstract void f3840();
+    public abstract void f3841();
+    public abstract void f3842();
+    public abstract void f3843();
+    public abstract void f3844();
+    public abstract void f3845();
+    public abstract void f3846();
+    public abstract void f3847();
+    public abstract void f3848();
+    public abstract void f3849();
+    public abstract void f3850();
+    public abstract void f3851();
+    public abstract void f3852();
+    public abstract void f3853();
+    public abstract void f3854();
+    public abstract void f3855();
+    public abstract void f3856();
+    public abstract void f3857();
+    public abstract void f3858();
+    public abstract void f3859();
+    public abstract void f3860();
+    public abstract void f3861();
+    public abstract void f3862();
+    public abstract void f3863();
+    public abstract void f3864();
+    public abstract void f3865();
+    public abstract void f3866();
+    public abstract void f3867();
+    public abstract void f3868();
+    public abstract void f3869();
+    public abstract void f3870();
+    public abstract void f3871();
+    public abstract void f3872();
+    public abstract void f3873();
+    public abstract void f3874();
+    public abstract void f3875();
+    public abstract void f3876();
+    public abstract void f3877();
+    public abstract void f3878();
+    public abstract void f3879();
+    public abstract void f3880();
+    public abstract void f3881();
+    public abstract void f3882();
+    public abstract void f3883();
+    public abstract void f3884();
+    public abstract void f3885();
+    public abstract void f3886();
+    public abstract void f3887();
+    public abstract void f3888();
+    public abstract void f3889();
+    public abstract void f3890();
+    public abstract void f3891();
+    public abstract void f3892();
+    public abstract void f3893();
+    public abstract void f3894();
+    public abstract void f3895();
+    public abstract void f3896();
+    public abstract void f3897();
+    public abstract void f3898();
+    public abstract void f3899();
+    public abstract void f3900();
+    public abstract void f3901();
+    public abstract void f3902();
+    public abstract void f3903();
+    public abstract void f3904();
+    public abstract void f3905();
+    public abstract void f3906();
+    public abstract void f3907();
+    public abstract void f3908();
+    public abstract void f3909();
+    public abstract void f3910();
+    public abstract void f3911();
+    public abstract void f3912();
+    public abstract void f3913();
+    public abstract void f3914();
+    public abstract void f3915();
+    public abstract void f3916();
+    public abstract void f3917();
+    public abstract void f3918();
+    public abstract void f3919();
+    public abstract void f3920();
+    public abstract void f3921();
+    public abstract void f3922();
+    public abstract void f3923();
+    public abstract void f3924();
+    public abstract void f3925();
+    public abstract void f3926();
+    public abstract void f3927();
+    public abstract void f3928();
+    public abstract void f3929();
+    public abstract void f3930();
+    public abstract void f3931();
+    public abstract void f3932();
+    public abstract void f3933();
+    public abstract void f3934();
+    public abstract void f3935();
+    public abstract void f3936();
+    public abstract void f3937();
+    public abstract void f3938();
+    public abstract void f3939();
+    public abstract void f3940();
+    public abstract void f3941();
+    public abstract void f3942();
+    public abstract void f3943();
+    public abstract void f3944();
+    public abstract void f3945();
+    public abstract void f3946();
+    public abstract void f3947();
+    public abstract void f3948();
+    public abstract void f3949();
+    public abstract void f3950();
+    public abstract void f3951();
+    public abstract void f3952();
+    public abstract void f3953();
+    public abstract void f3954();
+    public abstract void f3955();
+    public abstract void f3956();
+    public abstract void f3957();
+    public abstract void f3958();
+    public abstract void f3959();
+    public abstract void f3960();
+    public abstract void f3961();
+    public abstract void f3962();
+    public abstract void f3963();
+    public abstract void f3964();
+    public abstract void f3965();
+    public abstract void f3966();
+    public abstract void f3967();
+    public abstract void f3968();
+    public abstract void f3969();
+    public abstract void f3970();
+    public abstract void f3971();
+    public abstract void f3972();
+    public abstract void f3973();
+    public abstract void f3974();
+    public abstract void f3975();
+    public abstract void f3976();
+    public abstract void f3977();
+    public abstract void f3978();
+    public abstract void f3979();
+    public abstract void f3980();
+    public abstract void f3981();
+    public abstract void f3982();
+    public abstract void f3983();
+    public abstract void f3984();
+    public abstract void f3985();
+    public abstract void f3986();
+    public abstract void f3987();
+    public abstract void f3988();
+    public abstract void f3989();
+    public abstract void f3990();
+    public abstract void f3991();
+    public abstract void f3992();
+    public abstract void f3993();
+    public abstract void f3994();
+    public abstract void f3995();
+    public abstract void f3996();
+    public abstract void f3997();
+    public abstract void f3998();
+    public abstract void f3999();
+    public abstract void f4000();
+    public abstract void f4001();
+    public abstract void f4002();
+    public abstract void f4003();
+    public abstract void f4004();
+    public abstract void f4005();
+    public abstract void f4006();
+    public abstract void f4007();
+    public abstract void f4008();
+    public abstract void f4009();
+    public abstract void f4010();
+    public abstract void f4011();
+    public abstract void f4012();
+    public abstract void f4013();
+    public abstract void f4014();
+    public abstract void f4015();
+    public abstract void f4016();
+    public abstract void f4017();
+    public abstract void f4018();
+    public abstract void f4019();
+    public abstract void f4020();
+    public abstract void f4021();
+    public abstract void f4022();
+    public abstract void f4023();
+    public abstract void f4024();
+    public abstract void f4025();
+    public abstract void f4026();
+    public abstract void f4027();
+    public abstract void f4028();
+    public abstract void f4029();
+    public abstract void f4030();
+    public abstract void f4031();
+    public abstract void f4032();
+    public abstract void f4033();
+    public abstract void f4034();
+    public abstract void f4035();
+    public abstract void f4036();
+    public abstract void f4037();
+    public abstract void f4038();
+    public abstract void f4039();
+    public abstract void f4040();
+    public abstract void f4041();
+    public abstract void f4042();
+    public abstract void f4043();
+    public abstract void f4044();
+    public abstract void f4045();
+    public abstract void f4046();
+    public abstract void f4047();
+    public abstract void f4048();
+    public abstract void f4049();
+    public abstract void f4050();
+    public abstract void f4051();
+    public abstract void f4052();
+    public abstract void f4053();
+    public abstract void f4054();
+    public abstract void f4055();
+    public abstract void f4056();
+    public abstract void f4057();
+    public abstract void f4058();
+    public abstract void f4059();
+    public abstract void f4060();
+    public abstract void f4061();
+    public abstract void f4062();
+    public abstract void f4063();
+    public abstract void f4064();
+    public abstract void f4065();
+    public abstract void f4066();
+    public abstract void f4067();
+    public abstract void f4068();
+    public abstract void f4069();
+    public abstract void f4070();
+    public abstract void f4071();
+    public abstract void f4072();
+    public abstract void f4073();
+    public abstract void f4074();
+    public abstract void f4075();
+    public abstract void f4076();
+    public abstract void f4077();
+    public abstract void f4078();
+    public abstract void f4079();
+    public abstract void f4080();
+    public abstract void f4081();
+    public abstract void f4082();
+    public abstract void f4083();
+    public abstract void f4084();
+    public abstract void f4085();
+    public abstract void f4086();
+    public abstract void f4087();
+    public abstract void f4088();
+    public abstract void f4089();
+    public abstract void f4090();
+    public abstract void f4091();
+    public abstract void f4092();
+    public abstract void f4093();
+    public abstract void f4094();
+    public abstract void f4095();
+    public abstract void f4096();
+    public abstract void f4097();
+    public abstract void f4098();
+    public abstract void f4099();
+    public abstract void f4100();
+    public abstract void f4101();
+    public abstract void f4102();
+    public abstract void f4103();
+    public abstract void f4104();
+    public abstract void f4105();
+    public abstract void f4106();
+    public abstract void f4107();
+    public abstract void f4108();
+    public abstract void f4109();
+    public abstract void f4110();
+    public abstract void f4111();
+    public abstract void f4112();
+    public abstract void f4113();
+    public abstract void f4114();
+    public abstract void f4115();
+    public abstract void f4116();
+    public abstract void f4117();
+    public abstract void f4118();
+    public abstract void f4119();
+    public abstract void f4120();
+    public abstract void f4121();
+    public abstract void f4122();
+    public abstract void f4123();
+    public abstract void f4124();
+    public abstract void f4125();
+    public abstract void f4126();
+    public abstract void f4127();
+    public abstract void f4128();
+    public abstract void f4129();
+    public abstract void f4130();
+    public abstract void f4131();
+    public abstract void f4132();
+    public abstract void f4133();
+    public abstract void f4134();
+    public abstract void f4135();
+    public abstract void f4136();
+    public abstract void f4137();
+    public abstract void f4138();
+    public abstract void f4139();
+    public abstract void f4140();
+    public abstract void f4141();
+    public abstract void f4142();
+    public abstract void f4143();
+    public abstract void f4144();
+    public abstract void f4145();
+    public abstract void f4146();
+    public abstract void f4147();
+    public abstract void f4148();
+    public abstract void f4149();
+    public abstract void f4150();
+    public abstract void f4151();
+    public abstract void f4152();
+    public abstract void f4153();
+    public abstract void f4154();
+    public abstract void f4155();
+    public abstract void f4156();
+    public abstract void f4157();
+    public abstract void f4158();
+    public abstract void f4159();
+    public abstract void f4160();
+    public abstract void f4161();
+    public abstract void f4162();
+    public abstract void f4163();
+    public abstract void f4164();
+    public abstract void f4165();
+    public abstract void f4166();
+    public abstract void f4167();
+    public abstract void f4168();
+    public abstract void f4169();
+    public abstract void f4170();
+    public abstract void f4171();
+    public abstract void f4172();
+    public abstract void f4173();
+    public abstract void f4174();
+    public abstract void f4175();
+    public abstract void f4176();
+    public abstract void f4177();
+    public abstract void f4178();
+    public abstract void f4179();
+    public abstract void f4180();
+    public abstract void f4181();
+    public abstract void f4182();
+    public abstract void f4183();
+    public abstract void f4184();
+    public abstract void f4185();
+    public abstract void f4186();
+    public abstract void f4187();
+    public abstract void f4188();
+    public abstract void f4189();
+    public abstract void f4190();
+    public abstract void f4191();
+    public abstract void f4192();
+    public abstract void f4193();
+    public abstract void f4194();
+    public abstract void f4195();
+    public abstract void f4196();
+    public abstract void f4197();
+    public abstract void f4198();
+    public abstract void f4199();
+    public abstract void f4200();
+    public abstract void f4201();
+    public abstract void f4202();
+    public abstract void f4203();
+    public abstract void f4204();
+    public abstract void f4205();
+    public abstract void f4206();
+    public abstract void f4207();
+    public abstract void f4208();
+    public abstract void f4209();
+    public abstract void f4210();
+    public abstract void f4211();
+    public abstract void f4212();
+    public abstract void f4213();
+    public abstract void f4214();
+    public abstract void f4215();
+    public abstract void f4216();
+    public abstract void f4217();
+    public abstract void f4218();
+    public abstract void f4219();
+    public abstract void f4220();
+    public abstract void f4221();
+    public abstract void f4222();
+    public abstract void f4223();
+    public abstract void f4224();
+    public abstract void f4225();
+    public abstract void f4226();
+    public abstract void f4227();
+    public abstract void f4228();
+    public abstract void f4229();
+    public abstract void f4230();
+    public abstract void f4231();
+    public abstract void f4232();
+    public abstract void f4233();
+    public abstract void f4234();
+    public abstract void f4235();
+    public abstract void f4236();
+    public abstract void f4237();
+    public abstract void f4238();
+    public abstract void f4239();
+    public abstract void f4240();
+    public abstract void f4241();
+    public abstract void f4242();
+    public abstract void f4243();
+    public abstract void f4244();
+    public abstract void f4245();
+    public abstract void f4246();
+    public abstract void f4247();
+    public abstract void f4248();
+    public abstract void f4249();
+    public abstract void f4250();
+    public abstract void f4251();
+    public abstract void f4252();
+    public abstract void f4253();
+    public abstract void f4254();
+    public abstract void f4255();
+    public abstract void f4256();
+    public abstract void f4257();
+    public abstract void f4258();
+    public abstract void f4259();
+    public abstract void f4260();
+    public abstract void f4261();
+    public abstract void f4262();
+    public abstract void f4263();
+    public abstract void f4264();
+    public abstract void f4265();
+    public abstract void f4266();
+    public abstract void f4267();
+    public abstract void f4268();
+    public abstract void f4269();
+    public abstract void f4270();
+    public abstract void f4271();
+    public abstract void f4272();
+    public abstract void f4273();
+    public abstract void f4274();
+    public abstract void f4275();
+    public abstract void f4276();
+    public abstract void f4277();
+    public abstract void f4278();
+    public abstract void f4279();
+    public abstract void f4280();
+    public abstract void f4281();
+    public abstract void f4282();
+    public abstract void f4283();
+    public abstract void f4284();
+    public abstract void f4285();
+    public abstract void f4286();
+    public abstract void f4287();
+    public abstract void f4288();
+    public abstract void f4289();
+    public abstract void f4290();
+    public abstract void f4291();
+    public abstract void f4292();
+    public abstract void f4293();
+    public abstract void f4294();
+    public abstract void f4295();
+    public abstract void f4296();
+    public abstract void f4297();
+    public abstract void f4298();
+    public abstract void f4299();
+    public abstract void f4300();
+    public abstract void f4301();
+    public abstract void f4302();
+    public abstract void f4303();
+    public abstract void f4304();
+    public abstract void f4305();
+    public abstract void f4306();
+    public abstract void f4307();
+    public abstract void f4308();
+    public abstract void f4309();
+    public abstract void f4310();
+    public abstract void f4311();
+    public abstract void f4312();
+    public abstract void f4313();
+    public abstract void f4314();
+    public abstract void f4315();
+    public abstract void f4316();
+    public abstract void f4317();
+    public abstract void f4318();
+    public abstract void f4319();
+    public abstract void f4320();
+    public abstract void f4321();
+    public abstract void f4322();
+    public abstract void f4323();
+    public abstract void f4324();
+    public abstract void f4325();
+    public abstract void f4326();
+    public abstract void f4327();
+    public abstract void f4328();
+    public abstract void f4329();
+    public abstract void f4330();
+    public abstract void f4331();
+    public abstract void f4332();
+    public abstract void f4333();
+    public abstract void f4334();
+    public abstract void f4335();
+    public abstract void f4336();
+    public abstract void f4337();
+    public abstract void f4338();
+    public abstract void f4339();
+    public abstract void f4340();
+    public abstract void f4341();
+    public abstract void f4342();
+    public abstract void f4343();
+    public abstract void f4344();
+    public abstract void f4345();
+    public abstract void f4346();
+    public abstract void f4347();
+    public abstract void f4348();
+    public abstract void f4349();
+    public abstract void f4350();
+    public abstract void f4351();
+    public abstract void f4352();
+    public abstract void f4353();
+    public abstract void f4354();
+    public abstract void f4355();
+    public abstract void f4356();
+    public abstract void f4357();
+    public abstract void f4358();
+    public abstract void f4359();
+    public abstract void f4360();
+    public abstract void f4361();
+    public abstract void f4362();
+    public abstract void f4363();
+    public abstract void f4364();
+    public abstract void f4365();
+    public abstract void f4366();
+    public abstract void f4367();
+    public abstract void f4368();
+    public abstract void f4369();
+    public abstract void f4370();
+    public abstract void f4371();
+    public abstract void f4372();
+    public abstract void f4373();
+    public abstract void f4374();
+    public abstract void f4375();
+    public abstract void f4376();
+    public abstract void f4377();
+    public abstract void f4378();
+    public abstract void f4379();
+    public abstract void f4380();
+    public abstract void f4381();
+    public abstract void f4382();
+    public abstract void f4383();
+    public abstract void f4384();
+    public abstract void f4385();
+    public abstract void f4386();
+    public abstract void f4387();
+    public abstract void f4388();
+    public abstract void f4389();
+    public abstract void f4390();
+    public abstract void f4391();
+    public abstract void f4392();
+    public abstract void f4393();
+    public abstract void f4394();
+    public abstract void f4395();
+    public abstract void f4396();
+    public abstract void f4397();
+    public abstract void f4398();
+    public abstract void f4399();
+    public abstract void f4400();
+    public abstract void f4401();
+    public abstract void f4402();
+    public abstract void f4403();
+    public abstract void f4404();
+    public abstract void f4405();
+    public abstract void f4406();
+    public abstract void f4407();
+    public abstract void f4408();
+    public abstract void f4409();
+    public abstract void f4410();
+    public abstract void f4411();
+    public abstract void f4412();
+    public abstract void f4413();
+    public abstract void f4414();
+    public abstract void f4415();
+    public abstract void f4416();
+    public abstract void f4417();
+    public abstract void f4418();
+    public abstract void f4419();
+    public abstract void f4420();
+    public abstract void f4421();
+    public abstract void f4422();
+    public abstract void f4423();
+    public abstract void f4424();
+    public abstract void f4425();
+    public abstract void f4426();
+    public abstract void f4427();
+    public abstract void f4428();
+    public abstract void f4429();
+    public abstract void f4430();
+    public abstract void f4431();
+    public abstract void f4432();
+    public abstract void f4433();
+    public abstract void f4434();
+    public abstract void f4435();
+    public abstract void f4436();
+    public abstract void f4437();
+    public abstract void f4438();
+    public abstract void f4439();
+    public abstract void f4440();
+    public abstract void f4441();
+    public abstract void f4442();
+    public abstract void f4443();
+    public abstract void f4444();
+    public abstract void f4445();
+    public abstract void f4446();
+    public abstract void f4447();
+    public abstract void f4448();
+    public abstract void f4449();
+    public abstract void f4450();
+    public abstract void f4451();
+    public abstract void f4452();
+    public abstract void f4453();
+    public abstract void f4454();
+    public abstract void f4455();
+    public abstract void f4456();
+    public abstract void f4457();
+    public abstract void f4458();
+    public abstract void f4459();
+    public abstract void f4460();
+    public abstract void f4461();
+    public abstract void f4462();
+    public abstract void f4463();
+    public abstract void f4464();
+    public abstract void f4465();
+    public abstract void f4466();
+    public abstract void f4467();
+    public abstract void f4468();
+    public abstract void f4469();
+    public abstract void f4470();
+    public abstract void f4471();
+    public abstract void f4472();
+    public abstract void f4473();
+    public abstract void f4474();
+    public abstract void f4475();
+    public abstract void f4476();
+    public abstract void f4477();
+    public abstract void f4478();
+    public abstract void f4479();
+    public abstract void f4480();
+    public abstract void f4481();
+    public abstract void f4482();
+    public abstract void f4483();
+    public abstract void f4484();
+    public abstract void f4485();
+    public abstract void f4486();
+    public abstract void f4487();
+    public abstract void f4488();
+    public abstract void f4489();
+    public abstract void f4490();
+    public abstract void f4491();
+    public abstract void f4492();
+    public abstract void f4493();
+    public abstract void f4494();
+    public abstract void f4495();
+    public abstract void f4496();
+    public abstract void f4497();
+    public abstract void f4498();
+    public abstract void f4499();
+    public abstract void f4500();
+    public abstract void f4501();
+    public abstract void f4502();
+    public abstract void f4503();
+    public abstract void f4504();
+    public abstract void f4505();
+    public abstract void f4506();
+    public abstract void f4507();
+    public abstract void f4508();
+    public abstract void f4509();
+    public abstract void f4510();
+    public abstract void f4511();
+    public abstract void f4512();
+    public abstract void f4513();
+    public abstract void f4514();
+    public abstract void f4515();
+    public abstract void f4516();
+    public abstract void f4517();
+    public abstract void f4518();
+    public abstract void f4519();
+    public abstract void f4520();
+    public abstract void f4521();
+    public abstract void f4522();
+    public abstract void f4523();
+    public abstract void f4524();
+    public abstract void f4525();
+    public abstract void f4526();
+    public abstract void f4527();
+    public abstract void f4528();
+    public abstract void f4529();
+    public abstract void f4530();
+    public abstract void f4531();
+    public abstract void f4532();
+    public abstract void f4533();
+    public abstract void f4534();
+    public abstract void f4535();
+    public abstract void f4536();
+    public abstract void f4537();
+    public abstract void f4538();
+    public abstract void f4539();
+    public abstract void f4540();
+    public abstract void f4541();
+    public abstract void f4542();
+    public abstract void f4543();
+    public abstract void f4544();
+    public abstract void f4545();
+    public abstract void f4546();
+    public abstract void f4547();
+    public abstract void f4548();
+    public abstract void f4549();
+    public abstract void f4550();
+    public abstract void f4551();
+    public abstract void f4552();
+    public abstract void f4553();
+    public abstract void f4554();
+    public abstract void f4555();
+    public abstract void f4556();
+    public abstract void f4557();
+    public abstract void f4558();
+    public abstract void f4559();
+    public abstract void f4560();
+    public abstract void f4561();
+    public abstract void f4562();
+    public abstract void f4563();
+    public abstract void f4564();
+    public abstract void f4565();
+    public abstract void f4566();
+    public abstract void f4567();
+    public abstract void f4568();
+    public abstract void f4569();
+    public abstract void f4570();
+    public abstract void f4571();
+    public abstract void f4572();
+    public abstract void f4573();
+    public abstract void f4574();
+    public abstract void f4575();
+    public abstract void f4576();
+    public abstract void f4577();
+    public abstract void f4578();
+    public abstract void f4579();
+    public abstract void f4580();
+    public abstract void f4581();
+    public abstract void f4582();
+    public abstract void f4583();
+    public abstract void f4584();
+    public abstract void f4585();
+    public abstract void f4586();
+    public abstract void f4587();
+    public abstract void f4588();
+    public abstract void f4589();
+    public abstract void f4590();
+    public abstract void f4591();
+    public abstract void f4592();
+    public abstract void f4593();
+    public abstract void f4594();
+    public abstract void f4595();
+    public abstract void f4596();
+    public abstract void f4597();
+    public abstract void f4598();
+    public abstract void f4599();
+    public abstract void f4600();
+    public abstract void f4601();
+    public abstract void f4602();
+    public abstract void f4603();
+    public abstract void f4604();
+    public abstract void f4605();
+    public abstract void f4606();
+    public abstract void f4607();
+    public abstract void f4608();
+    public abstract void f4609();
+    public abstract void f4610();
+    public abstract void f4611();
+    public abstract void f4612();
+    public abstract void f4613();
+    public abstract void f4614();
+    public abstract void f4615();
+    public abstract void f4616();
+    public abstract void f4617();
+    public abstract void f4618();
+    public abstract void f4619();
+    public abstract void f4620();
+    public abstract void f4621();
+    public abstract void f4622();
+    public abstract void f4623();
+    public abstract void f4624();
+    public abstract void f4625();
+    public abstract void f4626();
+    public abstract void f4627();
+    public abstract void f4628();
+    public abstract void f4629();
+    public abstract void f4630();
+    public abstract void f4631();
+    public abstract void f4632();
+    public abstract void f4633();
+    public abstract void f4634();
+    public abstract void f4635();
+    public abstract void f4636();
+    public abstract void f4637();
+    public abstract void f4638();
+    public abstract void f4639();
+    public abstract void f4640();
+    public abstract void f4641();
+    public abstract void f4642();
+    public abstract void f4643();
+    public abstract void f4644();
+    public abstract void f4645();
+    public abstract void f4646();
+    public abstract void f4647();
+    public abstract void f4648();
+    public abstract void f4649();
+    public abstract void f4650();
+    public abstract void f4651();
+    public abstract void f4652();
+    public abstract void f4653();
+    public abstract void f4654();
+    public abstract void f4655();
+    public abstract void f4656();
+    public abstract void f4657();
+    public abstract void f4658();
+    public abstract void f4659();
+    public abstract void f4660();
+    public abstract void f4661();
+    public abstract void f4662();
+    public abstract void f4663();
+    public abstract void f4664();
+    public abstract void f4665();
+    public abstract void f4666();
+    public abstract void f4667();
+    public abstract void f4668();
+    public abstract void f4669();
+    public abstract void f4670();
+    public abstract void f4671();
+    public abstract void f4672();
+    public abstract void f4673();
+    public abstract void f4674();
+    public abstract void f4675();
+    public abstract void f4676();
+}
diff --git a/test/src/jdk/nashorn/test/models/JDK_8081015_TestModel.java b/test/src/jdk/nashorn/test/models/JDK_8081015_TestModel.java
new file mode 100644
index 0000000..069bc1b
--- /dev/null
+++ b/test/src/jdk/nashorn/test/models/JDK_8081015_TestModel.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.models;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+
+import java.util.Collection;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Queue;
+
+@SuppressWarnings("javadoc")
+public class JDK_8081015_TestModel {
+    private String lastInvoked;
+
+    public void receiveCollection(final Collection<Object> c) {
+        lastInvoked = "receiveCollection";
+        walkCollection(c);
+    }
+
+    public void receiveDeque(final Deque<Object> d) {
+        lastInvoked = "receiveDeque";
+        walkCollection(d);
+    }
+
+    public void receiveList(final List<Object> l) {
+        lastInvoked = "receiveList";
+        walkCollection(l);
+    }
+
+    public void receiveQueue(final Queue<Object> q) {
+        lastInvoked = "receiveQueue";
+        walkCollection(q);
+    }
+
+    public String getLastInvoked() {
+        return lastInvoked;
+    }
+
+    private static void walkCollection(final Collection<Object> c) {
+        final Iterator<Object> it = c.iterator();
+        assertEquals(it.next(), Integer.valueOf(1));
+        assertEquals(it.next(), Integer.valueOf(2));
+        assertEquals(it.next(), Double.valueOf(3.3));
+        assertEquals(it.next(), "foo");
+        assertFalse(it.hasNext());
+    }
+}
diff --git a/test/src/jdk/nashorn/test/models/Jdk8072596TestSubject.java b/test/src/jdk/nashorn/test/models/Jdk8072596TestSubject.java
new file mode 100644
index 0000000..cc95e01
--- /dev/null
+++ b/test/src/jdk/nashorn/test/models/Jdk8072596TestSubject.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.models;
+
+import java.util.List;
+import java.util.Map;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
+import jdk.nashorn.internal.runtime.ScriptObject;
+import org.testng.Assert;
+
+public class Jdk8072596TestSubject {
+
+    public Jdk8072596TestSubject(final Object x) {
+        Assert.assertTrue(x instanceof ScriptObjectMirror);
+        Assert.assertEquals(((ScriptObjectMirror)x).get("bar"), 0);
+    }
+
+    // Test having to wrap some arguments but not others
+    public void test1(final String x, final Object y, final ScriptObject w) {
+        Assert.assertEquals(x, "true");
+
+        Assert.assertTrue(y instanceof ScriptObjectMirror);
+        Assert.assertEquals(((ScriptObjectMirror)y).get("foo"), 1);
+
+        Assert.assertEquals(w.get("bar"), 2);
+    }
+
+    // Test having to wrap some arguments but not others, and a vararg array
+    public void test2(String x, final Object y, final ScriptObject w, final Object... z) {
+        test1(x, y, w);
+
+        Assert.assertEquals(z.length, 2);
+
+        Assert.assertTrue(z[0] instanceof ScriptObjectMirror);
+        Assert.assertEquals(((ScriptObjectMirror)z[0]).get("baz"), 3);
+
+        Assert.assertTrue(z[1] instanceof ScriptObjectMirror);
+        Assert.assertEquals(((ScriptObjectMirror)z[1]).get("bing"), 4);
+    }
+
+    // Test mixed (wrappable and non-wrappable) elements in a vararg array
+    public void test3(final Object... z) {
+        Assert.assertEquals(z.length, 5);
+
+        Assert.assertEquals(z[0], true);
+
+        Assert.assertTrue(z[1] instanceof ScriptObjectMirror);
+        Assert.assertEquals(((ScriptObjectMirror)z[1]).get("foo"), 5);
+
+        Assert.assertEquals(z[2], "hello");
+
+        Assert.assertTrue(z[3] instanceof ScriptObjectMirror);
+        Assert.assertEquals(((ScriptObjectMirror)z[3]).getSlot(0), 6);
+        Assert.assertEquals(((ScriptObjectMirror)z[3]).getSlot(1), 7);
+
+        Assert.assertEquals(z[4], 8);
+    }
+
+    // test wrapping the first argument of a static method
+    public static void test4(final Object x) {
+        Assert.assertTrue(x instanceof ScriptObjectMirror);
+        Assert.assertEquals(((ScriptObjectMirror)x).get("foo"), 9);
+    }
+
+    public void testListHasWrappedObject(final List<?> l) {
+        Assert.assertEquals(l.size(), 1);
+        Assert.assertTrue(l.get(0) instanceof ScriptObjectMirror);
+        Assert.assertEquals(((ScriptObjectMirror)l.get(0)).get("foo"), 10);
+    }
+
+    public void testArrayHasWrappedObject(final Object[] a) {
+        Assert.assertEquals(a.length, 1);
+        Assert.assertTrue(a[0] instanceof ScriptObjectMirror);
+        Assert.assertEquals(((ScriptObjectMirror)a[0]).get("bar"), 11);
+    }
+
+    public void testMapHasWrappedObject(final Map<?, ?> m, final Object key) {
+        Assert.assertEquals(m.size(), 1);
+        Assert.assertTrue(key instanceof ScriptObjectMirror);
+        Assert.assertTrue(m.get(key) instanceof ScriptObjectMirror);
+        Assert.assertEquals(((ScriptObjectMirror)m.get(key)).get("bar"), 12);
+    }
+}
diff --git a/test/src/jdk/nashorn/test/models/NullProvider.java b/test/src/jdk/nashorn/test/models/NullProvider.java
index 128d119..ec9922d 100644
--- a/test/src/jdk/nashorn/test/models/NullProvider.java
+++ b/test/src/jdk/nashorn/test/models/NullProvider.java
@@ -1,5 +1,5 @@
 /*
- * 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
diff --git a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java b/test/src/jdk/nashorn/test/models/VarArgConsumer.java
similarity index 80%
copy from test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
copy to test/src/jdk/nashorn/test/models/VarArgConsumer.java
index dfcad5a..a9b5401 100644
--- a/test/src/jdk/nashorn/api/scripting/WindowEventHandler.java
+++ b/test/src/jdk/nashorn/test/models/VarArgConsumer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,9 +23,13 @@
  * questions.
  */
 
-package jdk.nashorn.api.scripting;
+package jdk.nashorn.test.models;
 
-@SuppressWarnings("javadoc")
-public interface WindowEventHandler {
-    public boolean loaded();
+/**
+ * Simple function interface with a varargs SAM method.
+ */
+@FunctionalInterface
+public interface VarArgConsumer {
+    public void apply(Object... o);
 }
+