diff options
1176 files changed, 188153 insertions, 1 deletions
@@ -1,4 +1,25 @@ +syntax: glob + ^build/ ^dist/ -/nbproject/private/ ^.hgtip +/nbproject/private/ +^webrev/ +webrev.zip +*.class +*.log +*.orig +hotspot.log +private.properties +genfiles.properties +private.xml +.DS_Store* +TEST-*.xml +TESTS-*.xml +report.xml +CC/ +jcov2/ +buildtools/nasgen/nbproject/private/ +buildtools/nasgen/dist/ +buildtools/nasgen/build/ +.idea/* diff --git a/ASSEMBLY_EXCEPTION b/ASSEMBLY_EXCEPTION new file mode 100644 index 00000000..8b7ac1d0 --- /dev/null +++ b/ASSEMBLY_EXCEPTION @@ -0,0 +1,27 @@ + +OPENJDK ASSEMBLY EXCEPTION + +The OpenJDK source code made available by Sun at openjdk.java.net and +openjdk.dev.java.net ("OpenJDK Code") is distributed under the terms of the +GNU General Public License <http://www.gnu.org/copyleft/gpl.html> version 2 +only ("GPL2"), with the following clarification and special exception. + + Linking this OpenJDK Code statically or dynamically with other code + is making a combined work based on this library. Thus, the terms + and conditions of GPL2 cover the whole combination. + + As a special exception, Sun gives you permission to link this + OpenJDK Code with certain code licensed by Sun as indicated at + http://openjdk.java.net/legal/exception-modules-2007-05-08.html + ("Designated Exception Modules") to produce an executable, + regardless of the license terms of the Designated Exception Modules, + and to copy and distribute the resulting executable under GPL2, + provided that the Designated Exception Modules continue to be + governed by the licenses under which they were offered by Sun. + +As such, it allows licensees and sublicensees of Sun's GPL2 OpenJDK Code to +build an executable that includes those portions of necessary code that Sun +could not provide under GPL2 (or that Sun has provided under GPL2 with the +Classpath exception). If you modify or add to the OpenJDK code, that new +GPL2 code may still be combined with Designated Exception Modules if the +new code is made subject to this exception by its copyright holder. diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..b40a0f45 --- /dev/null +++ b/LICENSE @@ -0,0 +1,347 @@ +The GNU General Public License (GPL) + +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Everyone is permitted to copy and distribute verbatim copies of this license +document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your freedom to share +and change it. By contrast, the GNU General Public License is intended to +guarantee your freedom to share and change free software--to make sure the +software is free for all its users. This General Public License applies to +most of the Free Software Foundation's software and to any other program whose +authors commit to using it. (Some other Free Software Foundation software is +covered by the GNU Library General Public License instead.) You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our +General Public Licenses are designed to make sure that you have the freedom to +distribute copies of free software (and charge for this service if you wish), +that you receive source code or can get it if you want it, that you can change +the software or use pieces of it in new free programs; and that you know you +can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny +you these rights or to ask you to surrender the rights. These restrictions +translate to certain responsibilities for you if you distribute copies of the +software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for +a fee, you must give the recipients all the rights that you have. You must +make sure that they, too, receive or can get the source code. And you must +show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) +offer you this license which gives you legal permission to copy, distribute +and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that +everyone understands that there is no warranty for this free software. If the +software is modified by someone else and passed on, we want its recipients to +know that what they have is not the original, so that any problems introduced +by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We +wish to avoid the danger that redistributors of a free program will +individually obtain patent licenses, in effect making the program proprietary. +To prevent this, we have made it clear that any patent must be licensed for +everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification +follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice +placed by the copyright holder saying it may be distributed under the terms of +this General Public License. The "Program", below, refers to any such program +or work, and a "work based on the Program" means either the Program or any +derivative work under copyright law: that is to say, a work containing the +Program or a portion of it, either verbatim or with modifications and/or +translated into another language. (Hereinafter, translation is included +without limitation in the term "modification".) Each licensee is addressed as +"you". + +Activities other than copying, distribution and modification are not covered by +this License; they are outside its scope. The act of running the Program is +not restricted, and the output from the Program is covered only if its contents +constitute a work based on the Program (independent of having been made by +running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's source code as +you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this License +and to the absence of any warranty; and give any other recipients of the +Program a copy of this License along with the Program. + +You may charge a fee for the physical act of transferring a copy, and you may +at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion of it, thus +forming a work based on the Program, and copy and distribute such modifications +or work under the terms of Section 1 above, provided that you also meet all of +these conditions: + + a) You must cause the modified files to carry prominent notices stating + that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in whole or + in part contains or is derived from the Program or any part thereof, to be + licensed as a whole at no charge to all third parties under the terms of + this License. + + c) If the modified program normally reads commands interactively when run, + you must cause it, when started running for such interactive use in the + most ordinary way, to print or display an announcement including an + appropriate copyright notice and a notice that there is no warranty (or + else, saying that you provide a warranty) and that users may redistribute + the program under these conditions, and telling the user how to view a copy + of this License. (Exception: if the Program itself is interactive but does + not normally print such an announcement, your work based on the Program is + not required to print an announcement.) + +These requirements apply to the modified work as a whole. If identifiable +sections of that work are not derived from the Program, and can be reasonably +considered independent and separate works in themselves, then this License, and +its terms, do not apply to those sections when you distribute them as separate +works. But when you distribute the same sections as part of a whole which is a +work based on the Program, the distribution of the whole must be on the terms +of this License, whose permissions for other licensees extend to the entire +whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest your +rights to work written entirely by you; rather, the intent is to exercise the +right to control the distribution of derivative or collective works based on +the Program. + +In addition, mere aggregation of another work not based on the Program with the +Program (or with a work based on the Program) on a volume of a storage or +distribution medium does not bring the other work under the scope of this +License. + +3. You may copy and distribute the Program (or a work based on it, under +Section 2) in object code or executable form under the terms of Sections 1 and +2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable source + code, which must be distributed under the terms of Sections 1 and 2 above + on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three years, to + give any third party, for a charge no more than your cost of physically + performing source distribution, a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of Sections 1 + and 2 above on a medium customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer to + distribute corresponding source code. (This alternative is allowed only + for noncommercial distribution and only if you received the program in + object code or executable form with such an offer, in accord with + Subsection b above.) + +The source code for a work means the preferred form of the work for making +modifications to it. For an executable work, complete source code means all +the source code for all modules it contains, plus any associated interface +definition files, plus the scripts used to control compilation and installation +of the executable. However, as a special exception, the source code +distributed need not include anything that is normally distributed (in either +source or binary form) with the major components (compiler, kernel, and so on) +of the operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the source +code from the same place counts as distribution of the source code, even though +third parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as +expressly provided under this License. Any attempt otherwise to copy, modify, +sublicense or distribute the Program is void, and will automatically terminate +your rights under this License. However, parties who have received copies, or +rights, from you under this License will not have their licenses terminated so +long as such parties remain in full compliance. + +5. You are not required to accept this License, since you have not signed it. +However, nothing else grants you permission to modify or distribute the Program +or its derivative works. These actions are prohibited by law if you do not +accept this License. Therefore, by modifying or distributing the Program (or +any work based on the Program), you indicate your acceptance of this License to +do so, and all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), +the recipient automatically receives a license from the original licensor to +copy, distribute or modify the Program subject to these terms and conditions. +You may not impose any further restrictions on the recipients' exercise of the +rights granted herein. You are not responsible for enforcing compliance by +third parties to this License. + +7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), conditions +are imposed on you (whether by court order, agreement or otherwise) that +contradict the conditions of this License, they do not excuse you from the +conditions of this License. If you cannot distribute so as to satisfy +simultaneously your obligations under this License and any other pertinent +obligations, then as a consequence you may not distribute the Program at all. +For example, if a patent license would not permit royalty-free redistribution +of the Program by all those who receive copies directly or indirectly through +you, then the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply and +the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any patents or +other property right claims or to contest validity of any such claims; this +section has the sole purpose of protecting the integrity of the free software +distribution system, which is implemented by public license practices. Many +people have made generous contributions to the wide range of software +distributed through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing to +distribute software through any other system and a licensee cannot impose that +choice. + +This section is intended to make thoroughly clear what is believed to be a +consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in certain +countries either by patents or by copyrighted interfaces, the original +copyright holder who places the Program under this License may add an explicit +geographical distribution limitation excluding those countries, so that +distribution is permitted only in or among countries not thus excluded. In +such case, this License incorporates the limitation as if written in the body +of this License. + +9. The Free Software Foundation may publish revised and/or new versions of the +General Public License from time to time. Such new versions will be similar in +spirit to the present version, but may differ in detail to address new problems +or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any later +version", you have the option of following the terms and conditions either of +that version or of any later version published by the Free Software Foundation. +If the Program does not specify a version number of this License, you may +choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs +whose distribution conditions are different, write to the author to ask for +permission. For software which is copyrighted by the Free Software Foundation, +write to the Free Software Foundation; we sometimes make exceptions for this. +Our decision will be guided by the two goals of preserving the free status of +all derivatives of our free software and of promoting the sharing and reuse of +software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR +THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE +STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE +PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND +PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, +YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL +ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE +PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR +INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA +BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER +OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible +use to the public, the best way to achieve this is to make it free software +which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach +them to the start of each source file to most effectively convey the exclusion +of warranty; and each file should have at least the "copyright" line and a +pointer to where the full notice is found. + + One line to give the program's name and a brief idea of what it does. + + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it +starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author Gnomovision comes + with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free + software, and you are welcome to redistribute it under certain conditions; + type 'show c' for details. + +The hypothetical commands 'show w' and 'show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may be +called something other than 'show w' and 'show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, +if any, to sign a "copyright disclaimer" for the program, if necessary. Here +is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + 'Gnomovision' (which makes passes at compilers) written by James Hacker. + + signature of Ty Coon, 1 April 1989 + + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General Public +License instead of this License. + + +"CLASSPATH" EXCEPTION TO THE GPL + +Certain source files distributed by Oracle America and/or its affiliates are +subject to the following clarification and special exception to the GPL, but +only where Oracle has expressly included in the particular source file's header +the words "Oracle designates this particular file as subject to the "Classpath" +exception as provided by Oracle in the LICENSE file that accompanied this code." + + Linking this library statically or dynamically with other modules is making + a combined work based on this library. Thus, the terms and conditions of + the GNU General Public License cover the whole combination. + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent modules, + and to copy and distribute the resulting executable under terms of your + choice, provided that you also meet, for each linked independent module, + the terms and conditions of the license of that module. An independent + module is a module which is not derived from or based on this library. If + you modify this library, you may extend this exception to your version of + the library, but you are not obligated to do so. If you do not wish to do + so, delete this exception statement from your version. @@ -0,0 +1,147 @@ +- What is Nashorn? + +Nashorn is a runtime environment for programs written in ECMAScript 5.1 +that runs on top of JVM. + +- How to find out more about ECMAScript 5.1? + +The specification can be found at + + http://www.ecma-international.org/publications/standards/Ecma-262.htm + +- How to checkout sources of Nashorn project? + +Nashorn project uses Mercurial source code control system. You can +download Mercurial from http://mercurial.selenic.com/wiki/Download + +Information about the forest extension can be found at + + http://mercurial.selenic.com/wiki/ForestExtension + +and downlaoded using + + hg clone https://bitbucket.org/gxti/hgforest + +You can clone Nashorn Mercurial forest using this command: + + hg fclone http://hg.openjdk.java.net/nashorn/jdk8 nashorn~jdk8 + +To update your copy of the forest (fwith the latest code: + + (cd nashorn~jdk8 ; hg fpull) + +Or just the nashorn subdirectory with + + (cd nashorn~jdk8/nashorn ; hg pull -u) + +To learn about Mercurial in detail, please visit http://hgbook.red-bean.com. + +- How to build? + +To build Nashorn, you need to install JDK 8. You may use the Nashorn +forest build (recommended) or down load from java.net. You will need to +set JAVA_HOME environmental variable to point to your JDK installation +directory. + + cd nashorn~jdk8/nashorn/make + ant clean; ant + +- How to run? + +Use the jjs script (see RELESE_README): + + cd nashorn~jdk8/nashorn + sh bin/jjs <your .js file> + +Nashorn supports javax.script API. It is possible to drop nashorn.jar in +class path and request for "nashorn" script engine from +javax.script.ScriptEngineManager. + +Look for samples under the directory test/src/jdk/nashorn/api/scripting/. + +- Documentation + +Comprehensive development documentation is found in the Nashorn JavaDoc. You can +build it using: + + cd nashorn~jdk8/nashorn/make + ant javadoc + +after which you can view the generated documentation at dist/javadoc/index.html. + +- Running tests + +Nashorn tests are TestNG based. Running tests requires downloading the +TestNG library and placing its jar file into the lib subdirectory: + + # 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: + cd make + ant test + +You can also run the ECMA-262 test suite with Nashorn. In order to do +that, you will need to get a copy of it and put it in +test/script/external/test262 directory. A convenient way to do it is: + + hg clone http://hg.ecmascript.org/tests/test262/ test/script/external/test262 + +Alternatively, you can check it out elsewhere and make +test/script/external/test262 a symbolic link to that directory. After +you've done this, you can run the ECMA-262 tests using: + + cd nashorn~jdk8/nashorn/make + ant test262 + +These tests take time, so we have a parallelized runner for them that +takes advantage of all processor cores on the computer: + + cd nashorn~jdk8/nashorn/make + ant test262parallel + +- How to write your own test? + +Nashorn uses it's own simple test framework. Any .js file dropped under +nashorn/test directory is considered as a test. A test file can +optionally have .js.EXPECTED (foo.js.EXPECTED for foo.js) associated +with it. The .EXPECTED file, if exists, should contain the output +expected from compiling and/or running the test file. + +The test runner crawls these directories for .js files and looks for +JTReg-style @foo comments to identify tests. + + * @test - A test is tagged with @test. + + * @test/fail - Tests that are supposed to fail (compiling, see @run/fail + for runtime) are tagged with @test/fail. + + * @test/compile-error - Test expects compilation to fail, compares + output. + + * @test/warning - Test expects compiler warnings, compares output. + + * @test/nocompare - Test expects to compile [and/or run?] + successfully(may be warnings), does not compare output. + + * @subtest - denotes necessary file for a main test file; itself is not + a test. + + * @run - A test that should be run is also tagged with @run (otherwise + the test runner only compiles the test). + + * @run/fail - A test that should compile but fail with a runtime error. + + * @run/ignore-std-error - script may produce output on stderr, ignore + this output. + + * @argument - pass an argument to script. + + * @option \ - pass option to engine, sample. + +/** + * @option --dump-ir-graph + * @test + */ diff --git a/RELEASE_README b/RELEASE_README new file mode 100644 index 00000000..9984be4c --- /dev/null +++ b/RELEASE_README @@ -0,0 +1,20 @@ +The Nashorn repo is in the process of being migrated to OpenJDK and as such is +incomplete in several areas. + +- The build system is not fully integrated. When complete, Nashorn will be +installed in its proper location in the JRE. + +- Once integrated, the correct version of the JDK will be wrapped around +Nashorn. In the meantime, ensure you use JDK8 b68 or later. + +- The jjs tool has not been implemented in binary form yet. Use "sh bin/jjs" +(or bin/jjs.bat on windows) in the interm. + +- The Dynalink component is not fully integrated into Nashorn as yet, but will +be when details are finalized. + +- And, finally Nashorn is still in development. To stay up to date, subscribe +to nashorn-dev@openjdk.java.net at + + http://mail.openjdk.java.net/mailman/listinfo/nashorn-dev. + diff --git a/THIRD_PARTY_README b/THIRD_PARTY_README new file mode 100644 index 00000000..44318349 --- /dev/null +++ b/THIRD_PARTY_README @@ -0,0 +1,69 @@ +DO NOT TRANSLATE OR LOCALIZE. +----------------------------- + +%% This notice is provided with respect to ECMAScript Language +Specification ECMA-262 Edition 5.1 which is included with the Nashorn +technology. + +--- begin of LICENSE --- +Copyright notice +Copyright © 2011 Ecma International +Ecma International +Rue du Rhone 114 +CH-1204 Geneva +Tel: +41 22 849 6000 +Fax: +41 22 849 6001 +Web: http://www.ecma-international.org + +This document and possible translations of it may be copied and furnished to +others, and derivative works that comment on or otherwise explain it or assist +in its implementation may be prepared, copied, published, and distributed, in +whole or in part, without restriction of any kind, provided that the above +copyright notice and this section are included on all such copies and derivative +works. However, this document itself may not be modified in any way, including +by removing the copyright notice or references to Ecma International, except as +needed for the purpose of developing any document or deliverable produced by +Ecma International (in which case the rules applied to copyrights must be +followed) or as required to translate it into languages other than English. The +limited permissions granted above are perpetual and will not be revoked by Ecma +International or its successors or assigns. This document and the information +contained herein is provided on an "AS IS" basis and ECMA INTERNATIONAL +DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY +WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY OWNERSHIP +RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR +PURPOSE." Software License + +All Software contained in this document ("Software)" is protected by copyright +and is being made available under the "BSD License", included below. This +Software may be subject to third party rights (rights from parties other than +Ecma International), including patent rights, and no licenses under such third +party rights are granted under this license even if the third party concerned is +a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS +AVAILABLE AT http://www.ecma-international.org/memento/codeofconduct.htm FOR +INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO +IMPLEMENT ECMA INTERNATIONAL STANDARDS*. Redistribution and use in source and +binary forms, with or without modification, are permitted provided that the +following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the authors nor Ecma International may be used to endorse +or promote products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "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 ECMA INTERNATIONAL 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. +--- end of LICENSE --- diff --git a/bin/checkintest.sh b/bin/checkintest.sh new file mode 100644 index 00000000..a4750d58 --- /dev/null +++ b/bin/checkintest.sh @@ -0,0 +1,266 @@ +#!/bin/bash +# +# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +#best pass rate at test 262 known +TEST262_PASS_AT_LEAST=435 + +RUN_TEST="true" +RUN_TEST262="true" +RUN_NODE="true" +KEEP_OUTPUT="true" +CLEAN_AND_BUILD_NASHORN="true" + +#the stable node version to sync against +NODE_LAST_STABLE=v0.6.18 + +#parse args +for arg in $* +do + if [ $arg = "--no-test" ]; then + RUN_TEST="false" + echo "**** WARNING - you have disabled 'ant test', which is a minimum checkin requirement..." + elif [ $arg = "--no-262" ]; then + RUN_TEST262="false" + elif [ $arg = "--no-node" ]; then + RUN_NODE="false" + elif [ $arg = "--no-build" ]; then + CLEAN_AND_BUILD_NASHORN="false" + elif [ $arg = "--no-logs" ]; then + KEEP_OUTPUT="false" + fi +done + +function lastpart() { + arr=$(echo $1 | tr "/" "\n") + for x in $arr + do + _last=$x + done + echo $_last +} + +function check_installed() { + which $1 >/dev/null + if [ $? -ne 0 ]; then + echo "Error $1 not installed: $?" + exit 2 + fi +} + +check_installed hg +check_installed git +check_installed mv +check_installed git + +PWD=$(pwd); + +while [ -z $NASHORN_ROOT ] +do + if [ -e $PWD/.hg ]; then + NASHORN_ROOT=${PWD} + break + fi + PWD=$(dirname ${PWD}) +done + +echo "Nashorn root detected at ${NASHORN_ROOT}" + +COMMON_ROOT=$(dirname $NASHORN_ROOT) +echo "Common root is ${COMMON_ROOT}" + +echo "Running checkintest..." + +ABSOLUTE_NASHORN_HOME=$COMMON_ROOT/$(lastpart $NASHORN_ROOT) + +if [ $CLEAN_AND_BUILD_NASHORN != "false" ]; then + echo "Cleaning and building nashorn at $ABSOLUTE_NASHORN_HOME/nashorn..." + $(cd $ABSOLUTE_NASHORN_HOME/nashorn; ant clean >/dev/null 2>/dev/null) + $(cd $ABSOLUTE_NASHORN_HOME/nashorn; ant jar >/dev/null 2>/dev/null) + echo "Done." +fi + +function failure_check() { + while read line + do + LINE=$(echo $line | grep "Tests run") + if [ "${LINE}" != "" ]; then + RESULT=$(echo $line | grep "Failures: 0" | grep "Errors: 0") + if [ "${RESULT}" == "" ]; then + TESTNAME=$2 + echo "There were errors in ${TESTNAME} : ${LINE}" + exit 1 + fi + fi + done < $1 +} + +function test() { + TEST_OUTPUT=$ABSOLUTE_NASHORN_HOME/$(mktemp tmp.XXXXX) + echo "Running 'ant test' on nashorn from ${ABSOLUTE_NASHORN_HOME}/nashorn..." + $(cd $ABSOLUTE_NASHORN_HOME/nashorn; ant test >$TEST_OUTPUT) + echo "Done." + + failure_check $TEST_OUTPUT + + echo "**** SUCCESS: 'ant test' successful" + + if [ $KEEP_OUTPUT == "true" ]; then + cp $TEST_OUTPUT ./checkintest.test.log + rm -fr $TEST_OUTPUT + fi +} + +if [ $RUN_TEST != "false" ]; then + test; +fi + +function test262() { + + echo "Running 'ant test262parallel' on nashorn from ${ABSOLUTE_NASHORN_HOME}/nashorn..." + TEST262_OUTPUT=$ABSOLUTE_NASHORN_HOME/$(mktemp tmp.XXXXX) + + echo "Looking for ${ABSOLUTE_NASHORN_HOME}/test/test262..." + + if [ ! -e $ABSOLUTE_NASHORN_HOME/nashorn/test/test262 ]; then + echo "test262 is missing... looking in $COMMON_ROOT..." + if [ ! -e $COMMON_ROOT/test262 ]; then + echo "... not there either... cloning from repo..." + hg clone http://hg.ecmascript.org/tests/test262 $COMMON_ROOT/test262 >/dev/null 2>/dev/null + echo "Done." + fi + echo "Adding soft link ${COMMON_ROOT}/test262 -> ${ABSOLUTE_NASHORN_HOME}/test/test262..." + ln -s $COMMON_ROOT/test262 $ABSOLUTE_NASHORN_HOME/nashorn/test/test262 + echo "Done." + fi + + echo "Ensuring test262 is up to date..." + $(cd $ABSOLUTE_NASHORN_HOME/nashorn/test/test262; hg pull -u >/dev/null 2>/dev/null) + echo "Done." + + echo "Running test262..." + $(cd $ABSOLUTE_NASHORN_HOME/nashorn; ant test262parallel > $TEST262_OUTPUT) + + FAILED=$(cat $TEST262_OUTPUT|grep "Tests run:"| cut -d ' ' -f 15 |tr -cd '"[[:digit:]]') + if [ $FAILED -gt $TEST262_PASS_AT_LEAST ]; then + echo "FAILURE: There are ${FAILED} failures in test262 and can be no more than ${TEST262_PASS_AT_LEAST}" + cp $TEST262_OUTPUT ./checkintest.test262.log + echo "See ./checkintest.test262.log" + echo "Terminating due to error" + exit 1 + elif [ $FAILED -lt $TEST262_PASS_AT_LEAST ]; then + echo "There seem to have been fixes to 262. ${FAILED} < ${TEST262_PASS_AT_LEAST}. Please update limit in bin/checkintest.sh" + fi + + echo "**** SUCCESS: Test262 passed with no more than ${TEST262_PASS_AT_LEAST} failures." + + if [ $KEEP_OUTPUT == "true" ]; then + cp $TEST262_OUTPUT ./checkintest.test262.log + rm -fr $TEST262_OUTPUT + fi +} + +if [ $RUN_TEST262 != "false" ]; then + test262; +fi; + +function testnode() { + TESTNODEJAR_OUTPUT=$ABSOLUTE_NASHORN_HOME/$(mktemp tmp.XXXXX) + + echo "Running node tests..." +#replace node jar properties nashorn with this nashorn + + NODEJAR_PROPERTIES=~/nodejar.properties + + NODE_HOME=$(cat $NODEJAR_PROPERTIES | grep ^node.home | cut -f2 -d=) + NASHORN_HOME=$(cat $NODEJAR_PROPERTIES | grep ^nashorn.home | cut -f2 -d=) + + ABSOLUTE_NODE_HOME=$COMMON_ROOT/$(lastpart $NODE_HOME) + + echo "Writing nodejar.properties..." + + cat > $NODEJAR_PROPERTIES << EOF +node.home=../node +nashorn.home=../$(lastpart $NASHORN_ROOT) +EOF + echo "Done." + echo "Checking node home ${ABSOLUTE_NODE_HOME}..." + + if [ ! -e $ABSOLUTE_NODE_HOME ]; then + echo "Node base dir not found. Cloning node..." + $(cd $COMMON_ROOT; git clone https://github.com/joyent/node.git $(lastpart $NODE_HOME) >/dev/null 2>/dev/null) + echo "Done." + echo "Updating to last stable version ${NODE_LAST_STABLE}..." + $(cd $ABSOLUTE_NODE_HOME; git checkout $NODE_LAST_STABLE >/dev/null 2>/dev/null) + echo "Done." + echo "Running configure..." + $(cd $ABSOLUTE_NODE_HOME; ./configure >/dev/null 2>/dev/null) + echo "Done." + fi + + echo "Ensuring node is built..." +#make sure node is built + $(cd $ABSOLUTE_NODE_HOME; make >/dev/null 2>/dev/null) + echo "Done." + + NODEJAR_HOME=$COMMON_ROOT/nodejar + + if [ ! -e $NODEJAR_HOME ]; then + echo "No node jar home found. cloning from depot..." + $(cd $COMMON_ROOT; hg clone https://hg.kenai.com/hg/nodejs~source nodejar >/dev/null 2>/dev/null) + $(cd $COMMON_ROOT/nodejar; ant >/dev/null) + echo "Done." + echo "Copying node files..." + $(cd $COMMON_ROOT/nodejar; ant copy-node-files >/dev/null 2>/dev/null) + echo "Patching node files..." + $(cd $COMMON_ROOT/nodejar; ant patch-node-files >/dev/null 2>/dev/null) + echo "Done." + fi + + echo "Ensuring node.jar is up to date from source depot..." + $(cd $COMMON_ROOT/nodejar; hg pull -u >/dev/null 2>/dev/null) + echo "Done." + + echo "Installing nashorn..." + $(cd $COMMON_ROOT/nodejar; ant >/dev/null) + echo "Done." + + echo "Running node.jar test..." + $(cd $COMMON_ROOT/nodejar; mvn clean verify >$TESTNODEJAR_OUTPUT) + echo "Done." + + failure_check $TESTNODEJAR_OUTPUT + + echo "**** SUCCESS: Node test successful." + + if [ $KEEP_OUTPUT == "true" ]; then + rm -fr $TESTNODEJAR_OUTPUT + cp $TESTNODEJAR_OUTPUT ./checkintest.nodejar.log + fi +} + +if [ $RUN_NODE != "false" ]; then + testnode; +fi; + +echo "Finished" diff --git a/bin/fixorphantests.sh b/bin/fixorphantests.sh new file mode 100644 index 00000000..d7e5f74b --- /dev/null +++ b/bin/fixorphantests.sh @@ -0,0 +1,52 @@ +#!/bin/sh +# +# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +#ensure that all tests tagged with @test are also tagged with @run + +for f in $(find test/script/basic/*.js); do + grep @test $f >/dev/null + TEST=$? + grep @run $f >/dev/null + RUN=$? + + if [ $TEST -eq 0 ] && [ ! $RUN -eq 0 ]; then + echo "repairing ${f}..." + TEMP=$(mktemp /tmp/scratch.XXXXXX) + + #IFS='', -raw flag to preserve white space + while IFS='' read -r line; do + echo $line | grep @test >/dev/null + TEST=$? + printf "%s\n" "$line" + if [ $TEST -eq 0 ]; then + printf "%s\n" "$line" | sed s/@test/@run/g + fi + done < $f >$TEMP + + cp $TEMP $f + + rm -fr $TEMP + fi + +done diff --git a/bin/fixwhitespace.sh b/bin/fixwhitespace.sh new file mode 100644 index 00000000..921a233d --- /dev/null +++ b/bin/fixwhitespace.sh @@ -0,0 +1,30 @@ +#!/bin/bash +# +# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +#convert tabs to spaces +find . -name "*.java" -exec sed -i "" 's/ / /g' {} \; + +#remove trailing whitespace +find . -name "*.java" -exec sed -i "" 's/[ ]*$//' \{} \; + diff --git a/bin/jjs b/bin/jjs new file mode 100644 index 00000000..ae436b27 --- /dev/null +++ b/bin/jjs @@ -0,0 +1,29 @@ +#!/bin/bash +# +# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +[ -z "$JAVA_HOME" ] && echo "Please set JAVA_HOME" && exit 1; + +$JAVA_HOME/bin/java -server -XX:-TieredCompilation -Xms2G -Xmx2G -esa -ea -Djava.ext.dirs=$JAVA_HOME/jre/lib/ext:`dirname $0`/../dist -XX:+HeapDumpOnOutOfMemoryError -Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -Dnashorn.debug=true jdk.nashorn.tools.Shell $* diff --git a/bin/jjs.bat b/bin/jjs.bat new file mode 100644 index 00000000..a7169577 --- /dev/null +++ b/bin/jjs.bat @@ -0,0 +1,27 @@ +rem +rem Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +rem DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +rem +rem This code is free software; you can redistribute it and/or modify it +rem under the terms of the GNU General Public License version 2 only, as +rem published by the Free Software Foundation. Oracle designates this +rem particular file as subject to the "Classpath" exception as provided +rem by Oracle in the LICENSE file that accompanied this code. +rem +rem This code is distributed in the hope that it will be useful, but WITHOUT +rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +rem version 2 for more details (a copy is included in the LICENSE file that +rem accompanied this code). +rem +rem You should have received a copy of the GNU General Public License version +rem 2 along with this work; if not, write to the Free Software Foundation, +rem Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +rem +rem Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +rem or visit www.oracle.com if you need additional information or have any +rem questions. +rem +@echo off + +java -Xms2G -Xmx2G -XX:-TieredCompilation -server -esa -ea -Djava.ext.dirs=%~dp0\..\dist -XX:+HeapDumpOnOutOfMemoryError -Dnashorn.debug=true -Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false jdk.nashorn.tools.Shell diff --git a/bin/jjssecure b/bin/jjssecure new file mode 100644 index 00000000..887c421d --- /dev/null +++ b/bin/jjssecure @@ -0,0 +1,29 @@ +#!/bin/bash +# +# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +[ -z "$JAVA_HOME" ] && echo "Please set JAVA_HOME" && exit 1; + +$JAVA_HOME/bin/java -Xms2G -Xmx2G -XX:-TieredCompilation -server -esa -ea -Djava.ext.dirs=$JAVA_HOME/jre/lib/ext:`dirname $0`/../dist -XX:+HeapDumpOnOutOfMemoryError -Dnashorn.debug=true -Djava.lang.invoke.MethodHandle.DEBUG_NAMES=true -Dnashorn.home=`dirname $0`/.. -Djava.security.manager jdk.nashorn.tools.Shell $* diff --git a/bin/jjssecure.bat b/bin/jjssecure.bat new file mode 100644 index 00000000..662b167a --- /dev/null +++ b/bin/jjssecure.bat @@ -0,0 +1,27 @@ +rem +rem Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +rem DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +rem +rem This code is free software; you can redistribute it and/or modify it +rem under the terms of the GNU General Public License version 2 only, as +rem published by the Free Software Foundation. Oracle designates this +rem particular file as subject to the "Classpath" exception as provided +rem by Oracle in the LICENSE file that accompanied this code. +rem +rem This code is distributed in the hope that it will be useful, but WITHOUT +rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +rem version 2 for more details (a copy is included in the LICENSE file that +rem accompanied this code). +rem +rem You should have received a copy of the GNU General Public License version +rem 2 along with this work; if not, write to the Free Software Foundation, +rem Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +rem +rem Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +rem or visit www.oracle.com if you need additional information or have any +rem questions. +rem +@echo off + +java -Xms2G -Xmx2G -XX:-TieredCompilation -server -esa -ea -Djava.ext.dirs=%~dp0\..\dist -XX:+HeapDumpOnOutOfMemoryError -Dnashorn.debug=true -Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -Dnashorn.home=%~dp0\.. -Djava.security.manager jdk.nashorn.tools.Shell diff --git a/bin/nashorn b/bin/nashorn new file mode 100644 index 00000000..7720f423 --- /dev/null +++ b/bin/nashorn @@ -0,0 +1,29 @@ +#!/bin/bash +# +# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +[ -z "$JAVA_HOME" ] && echo "Please set JAVA_HOME" && exit 1; + +$JAVA_HOME/bin/jrunscript -J-Xms2G -J-Xmx2G -J-XX:-TieredCompilation -J-server -J-esa -J-ea -J-Djava.ext.dirs=$JAVA_HOME/jre/lib/ext:`dirname $0`/../dist -J-XX:+HeapDumpOnOutOfMemoryError -J-Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -J-Dnashorn.debug=true -l nashorn $* diff --git a/bin/nashorn.bat b/bin/nashorn.bat new file mode 100644 index 00000000..86aafc44 --- /dev/null +++ b/bin/nashorn.bat @@ -0,0 +1,27 @@ +rem +rem Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +rem DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +rem +rem This code is free software; you can redistribute it and/or modify it +rem under the terms of the GNU General Public License version 2 only, as +rem published by the Free Software Foundation. Oracle designates this +rem particular file as subject to the "Classpath" exception as provided +rem by Oracle in the LICENSE file that accompanied this code. +rem +rem This code is distributed in the hope that it will be useful, but WITHOUT +rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +rem version 2 for more details (a copy is included in the LICENSE file that +rem accompanied this code). +rem +rem You should have received a copy of the GNU General Public License version +rem 2 along with this work; if not, write to the Free Software Foundation, +rem Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +rem +rem Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +rem or visit www.oracle.com if you need additional information or have any +rem questions. +rem +@echo off + +jrunscript -J-Xms2G -J-Xmx2G -J-XX:-TieredCompilation -J-server -J-esa -J-ea -J-Djava.ext.dirs=%~dp0\..\dist -J-XX:+HeapDumpOnOutOfMemoryError -J-Dnashorn.debug=true -J-Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -l nashorn diff --git a/bin/rm-non-tracked.sh b/bin/rm-non-tracked.sh new file mode 100644 index 00000000..aaadcf38 --- /dev/null +++ b/bin/rm-non-tracked.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# +# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +hg status|grep ^\?|awk '{print $2}'|xargs rm diff --git a/bin/verbose_octane.bat b/bin/verbose_octane.bat new file mode 100644 index 00000000..69abbf8b --- /dev/null +++ b/bin/verbose_octane.bat @@ -0,0 +1,59 @@ +rem +rem Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +rem DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +rem +rem This code is free software; you can redistribute it and/or modify it +rem under the terms of the GNU General Public License version 2 only, as +rem published by the Free Software Foundation. +rem +rem This code is distributed in the hope that it will be useful, but WITHOUT +rem ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +rem FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +rem version 2 for more details (a copy is included in the LICENSE file that +rem accompanied this code). +rem +rem You should have received a copy of the GNU General Public License version +rem 2 along with this work; if not, write to the Free Software Foundation, +rem Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +rem +rem Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +rem or visit www.oracle.com if you need additional information or have any +rem questions. +rem +@echo off + +if "%JAVA_HOME%" neq "" ( + call :run "%JAVA_HOME%/bin/java" +) else ( + call :run java +) +goto :EOF + +:run +setlocal +set NASHORN_JAR=dist/nashorn.jar +set JVM_FLAGS=-Xms2G -Xmx2G -XX:-TieredCompilation -server -esa -ea -jar %NASHORN_JAR% +set JVM_FLAGS7=-Xbootclasspath/p:%NASHORN_JAR% %JVM_FLAGS% +set OCTANE_ARGS=--verbose --iterations 7 + +%1 -fullversion 2>&1 | findstr /L /C:"version ""1.7" +if %errorlevel% equ 0 ( + set CMD=%1 %JVM_FLAGS7% +) else ( + %1 -fullversion + set CMD=%1 %JVM_FLAGS% +) + +%CMD% test/script/basic/run-octane.js -- test/script/external/octane/benchmarks/box2d.js %OCTANE_ARGS% +%CMD% test/script/basic/run-octane.js -- test/script/external/octane/benchmarks/code-load.js %OCTANE_ARGS% +%CMD% test/script/basic/run-octane.js -- test/script/external/octane/benchmarks/crypto.js %OCTANE_ARGS% +%CMD% test/script/basic/run-octane.js -- test/script/external/octane/benchmarks/deltablue.js %OCTANE_ARGS% +%CMD% test/script/basic/run-octane.js -- test/script/external/octane/benchmarks/gbemu.js %OCTANE_ARGS% +%CMD% test/script/basic/run-octane.js -- test/script/external/octane/benchmarks/navier-stokes.js %OCTANE_ARGS% +%CMD% test/script/basic/run-octane.js -- test/script/external/octane/benchmarks/pdfjs.js %OCTANE_ARGS% +%CMD% test/script/basic/run-octane.js -- test/script/external/octane/benchmarks/raytrace.js %OCTANE_ARGS% +%CMD% test/script/basic/run-octane.js -- test/script/external/octane/benchmarks/regexp.js %OCTANE_ARGS% +%CMD% test/script/basic/run-octane.js -- test/script/external/octane/benchmarks/richards.js %OCTANE_ARGS% +%CMD% test/script/basic/run-octane.js -- test/script/external/octane/benchmarks/splay.js %OCTANE_ARGS% +endlocal +goto :EOF diff --git a/bin/verbose_octane.sh b/bin/verbose_octane.sh new file mode 100644 index 00000000..6a9b7eb3 --- /dev/null +++ b/bin/verbose_octane.sh @@ -0,0 +1,58 @@ +#!/bin/bash +# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +ITERS=$1 +if [ -z $ITERS ]; then + ITERS=7 +fi +NASHORN_JAR=dist/nashorn.jar +JVM_FLAGS="-XX:+UnlockDiagnosticVMOptions -Dnashorn.unstable.relink.threshold=8 -Xms2G -Xmx2G -XX:-TieredCompilation -server -jar ${NASHORN_JAR}" +JVM_FLAGS7="-Xbootclasspath/p:${NASHORN_JAR} ${JVM_FLAGS}" +OCTANE_ARGS="--verbose --iterations ${ITERS}" + +BENCHMARKS=( "box2d.js" "code-load.js" "crypto.js" "deltablue.js" "earley-boyer.js" "gbemu.js" "navier-stokes.js" "raytrace.js" "regexp.js" "richards.js" "splay.js" ) +# TODO mandreel.js has metaspace issues + +if [ ! -z $JAVA7_HOME ]; then + echo "running ${ITERS} iterations with java7 using JAVA_HOME=${JAVA7_HOME}..." + for BENCHMARK in "${BENCHMARKS[@]}" + do + CMD="${JAVA8_HOME}/bin/java ${JVM_FLAGS} test/script/basic/run-octane.js -- test/script/external/octane/benchmarks/${BENCHMARK} ${OCTANE_ARGS}" + $CMD + done +else + echo "no JAVA7_HOME set. skipping java7" +fi + +if [ ! -z $JAVA8_HOME ]; then + echo "running ${ITERS} iterations with java8 using JAVA_HOME=${JAVA8_HOME}..." + for BENCHMARK in "${BENCHMARKS[@]}" + do + CMD="${JAVA8_HOME}/bin/java ${JVM_FLAGS} test/script/basic/run-octane.js -- test/script/external/octane/benchmarks/${BENCHMARK} ${OCTANE_ARGS}" + $CMD + done +else + echo "no JAVA8_HOME set" +fi + +echo "Done" diff --git a/buildtools/nasgen/README b/buildtools/nasgen/README new file mode 100644 index 00000000..d4509459 --- /dev/null +++ b/buildtools/nasgen/README @@ -0,0 +1,34 @@ +Nasgen is a tool for processing Java classes that implement native +JavaScript objects. It does so by looking for the +com.oracle.nashorn.objects.annotations.ScriptClass annotation and other +annotations in that package. + +For each class "C", nasgen instruments the original class and generates +two additional classes: a "C$Prototype" class for the JavaScript +prototype object, and a "C$Constructor" class for the JavaScript +constructor function. + +Each class instrumented or generated by nasgen contains a private static +"$nasgenmap$" field of type com.oracle.nashorn.runtime.PropertyMap and +static initializer block to initialize the field to the object's +JavaScript properties. + +Members annotated with @Function, @Property, @Getter, and @Setter are +mapped to the $Constructor, $Prototype, or main class, depending on the +value of the annotation's 'where' field. By default, @Property, @Getter, +and @Setter belong to the main class while @Function methods without +explicit 'where' field belong to the $Prototype class. The @Constructor +annotation marks a method to be invoked as JavaScript constructor. + +Nasgen enforces all @Function/@Getter/@Setter/@Constructor annotated +methods to be declared as static. Static final @Property fields remain +in the main class while other @Property fields are moved to respective +classes depending on the annotation's 'where' value. For functions +mapped to the $Prototype or $Constructor class, nasgen also generates +getters and setters prefixed by G$ and S$, respectively. + +Nasgen-generated classes are hidden from normal ClassLoaders by giving +them a ".clazz" file name extension instead of the standard ".class" +extension. This allows script classes to be loaded independently by each +Nashorn context through the com.oracle.nashorn.runtime.StructureLoader +class loader. diff --git a/buildtools/nasgen/build.xml b/buildtools/nasgen/build.xml new file mode 100644 index 00000000..e20793b7 --- /dev/null +++ b/buildtools/nasgen/build.xml @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + or visit www.oracle.com if you need additional information or have any + questions. +--> +<project name="nasgen" default="all" basedir="."> + <target name="init"> + <loadproperties srcFile="project.properties"/> + </target> + + <target name="prepare" depends="init"> + <mkdir dir="${build.classes.dir}"/> + <mkdir dir="${dist.dir}"/> + <mkdir dir="${dist.dir}/lib"/> + </target> + + <target name="clean" depends="init"> + <delete dir="${build.dir}"/> + <delete dir="${dist.dir}"/> + </target> + + <target name="compile" depends="prepare" description="Compiles the nasgen sources"> + <javac srcdir="${src.dir}" + destdir="${build.classes.dir}" + classpath="${javac.classpath}" + debug="${javac.debug}" + includeantruntime="false"> + <compilerarg value="-Xlint:unchecked"/> + <compilerarg value="-Xlint:deprecation"/> + <compilerarg value="-XDignore.symbol.file"/> + </javac> + </target> + + <target name="jar" depends="compile" description="Creates nasgen.jar"> + <jar jarfile="${dist.jar}" basedir="${build.classes.dir}" manifest="${meta.inf.dir}/MANIFEST.MF"/> + </target> + + <target name="dist" depends="jar"/> + + <target name="all" depends="dist" + description="Builds sources and generates nasgen.jar"/> +</project> diff --git a/buildtools/nasgen/nasgen.iml b/buildtools/nasgen/nasgen.iml new file mode 100644 index 00000000..b67d39e9 --- /dev/null +++ b/buildtools/nasgen/nasgen.iml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + or visit www.oracle.com if you need additional information or have any + questions. +--> +<module type="JAVA_MODULE" version="4"> + <component name="NewModuleRootManager" inherit-compiler-output="false"> + <output url="file://$MODULE_DIR$/build/classes" /> + <output-test url="file://$MODULE_DIR$/build/test/classes" /> + <exclude-output /> + <content url="file://$MODULE_DIR$"> + <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> + <excludeFolder url="file://$MODULE_DIR$/build" /> + <excludeFolder url="file://$MODULE_DIR$/dist" /> + </content> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + <orderEntry type="module" module-name="asm" /> + </component> +</module> + diff --git a/buildtools/nasgen/project.properties b/buildtools/nasgen/project.properties new file mode 100644 index 00000000..65047d95 --- /dev/null +++ b/buildtools/nasgen/project.properties @@ -0,0 +1,52 @@ +# +# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +application.title=nasgen + +# source and target levels +build.compiler=modern +javac.source=1.7 +javac.target=1.7 + +build.classes.dir=${build.dir}/classes + +# This directory is removed when the project is cleaned: +build.dir=build + +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/nasgen.jar +dist.javadoc.dir=${dist.dir}/javadoc + +nashorn.dir=../../ + +javac.debug=true + +javac.classpath=\ + ${nashorn.dir}/build/classes + +meta.inf.dir=${src.dir}/META-INF +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +run.jvmargs= +src.dir=src diff --git a/buildtools/nasgen/src/META-INF/MANIFEST.MF b/buildtools/nasgen/src/META-INF/MANIFEST.MF new file mode 100644 index 00000000..b7098636 --- /dev/null +++ b/buildtools/nasgen/src/META-INF/MANIFEST.MF @@ -0,0 +1,4 @@ +Manifest-Version: 1.0
+Class-Path: lib/ant-1.7.1.jar
+Main-Class: jdk.nashorn.internal.tools.nasgen.Main
+
diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java new file mode 100644 index 00000000..3a78da41 --- /dev/null +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.tools.nasgen; + +import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PRIVATE; +import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC; +import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC; +import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC; +import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKEVIRTUAL; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.CLINIT; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.GETTER_PREFIX; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.GET_CLASS_NAME; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.GET_CLASS_NAME_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.LOOKUP_NEWPROPERTY; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.LOOKUP_NEWPROPERTY_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.LOOKUP_TYPE; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_FIELD_NAME; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_NEWMAP; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_NEWMAP_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_TYPE; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_TYPE; +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; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SETTER_PREFIX; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.TYPE_OBJECT; + +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.List; +import jdk.internal.org.objectweb.asm.ClassReader; +import jdk.internal.org.objectweb.asm.ClassVisitor; +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.FieldVisitor; +import jdk.internal.org.objectweb.asm.Handle; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Type; +import jdk.nashorn.internal.tools.nasgen.MemberInfo.Kind; + +/** + * Base class for class generator classes. + * + */ +public class ClassGenerator { + /** ASM class writer used to output bytecode for this class */ + protected final ClassWriter cw; + + /** + * Constructor + */ + protected ClassGenerator() { + this.cw = makeClassWriter(); + } + + MethodGenerator makeStaticInitializer() { + return makeStaticInitializer(cw); + } + + MethodGenerator makeConstructor() { + return makeConstructor(cw); + } + + MethodGenerator makeMethod(final int access, final String name, final String desc) { + return makeMethod(cw, access, name, desc); + } + + void addMapField() { + addMapField(cw); + } + + void addField(final String name, final String desc) { + addField(cw, name, desc); + } + + void addFunctionField(final String name) { + addFunctionField(cw, name); + } + + void addGetter(final String owner, final MemberInfo memInfo) { + addGetter(cw, owner, memInfo); + } + + void addSetter(final String owner, final MemberInfo memInfo) { + addSetter(cw, owner, memInfo); + } + + void emitGetClassName(final String name) { + final MethodGenerator mi = makeMethod(ACC_PUBLIC, GET_CLASS_NAME, GET_CLASS_NAME_DESC); + mi.loadLiteral(name); + mi.returnValue(); + mi.computeMaxs(); + mi.visitEnd(); + } + + static ClassWriter makeClassWriter() { + return new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) { + @Override + protected String getCommonSuperClass(final String type1, final String type2) { + try { + return super.getCommonSuperClass(type1, type2); + } catch (final RuntimeException | LinkageError e) { + return StringConstants.OBJECT_TYPE; + } + } + }; + } + + static MethodGenerator makeStaticInitializer(final ClassVisitor cv) { + return makeStaticInitializer(cv, CLINIT); + } + + static MethodGenerator makeStaticInitializer(final ClassVisitor cv, final String name) { + final int access = ACC_PUBLIC | ACC_STATIC; + final String desc = DEFAULT_INIT_DESC; + final MethodVisitor mv = cv.visitMethod(access, name, desc, null, null); + return new MethodGenerator(mv, access, name, desc); + } + + static MethodGenerator makeConstructor(final ClassVisitor cv) { + final int access = ACC_PUBLIC; + final String name = INIT; + final String desc = DEFAULT_INIT_DESC; + final MethodVisitor mv = cv.visitMethod(access, name, desc, null, null); + return new MethodGenerator(mv, access, name, desc); + } + + static MethodGenerator makeMethod(final ClassVisitor cv, final int access, final String name, final String desc) { + final MethodVisitor mv = cv.visitMethod(access, name, desc, null, null); + return new MethodGenerator(mv, access, name, desc); + } + + static void emitStaticInitPrefix(final MethodGenerator mi, final String className) { + mi.visitCode(); + mi.pushNull(); + mi.putStatic(className, MAP_FIELD_NAME, MAP_DESC); + mi.loadClass(className); + mi.invokeStatic(MAP_TYPE, MAP_NEWMAP, MAP_NEWMAP_DESC); + mi.storeLocal(0); + } + + static void emitStaticInitSuffix(final MethodGenerator mi, final String className) { + mi.loadLocal(0); + mi.putStatic(className, MAP_FIELD_NAME, MAP_DESC); + mi.returnVoid(); + mi.computeMaxs(); + mi.visitEnd(); + } + + @SuppressWarnings("fallthrough") + private static Type memInfoType(final MemberInfo memInfo) { + switch (memInfo.getJavaDesc().charAt(0)) { + case 'I': return Type.INT_TYPE; + case 'J': return Type.LONG_TYPE; + case 'D': return Type.DOUBLE_TYPE; + default: assert false : memInfo.getJavaDesc(); + case 'L': return TYPE_OBJECT; + } + } + + private static String getterDesc(final MemberInfo memInfo) { + return Type.getMethodDescriptor(memInfoType(memInfo)); + } + + private static String setterDesc(final MemberInfo memInfo) { + return Type.getMethodDescriptor(Type.VOID_TYPE, memInfoType(memInfo)); + } + + static void addGetter(final ClassVisitor cv, final String owner, final MemberInfo memInfo) { + final int access = ACC_PUBLIC; + final String name = GETTER_PREFIX + memInfo.getJavaName(); + final String desc = getterDesc(memInfo); + final MethodVisitor mv = cv.visitMethod(access, name, desc, null, null); + final MethodGenerator mi = new MethodGenerator(mv, access, name, desc); + mi.visitCode(); + if (memInfo.isStatic() && memInfo.getKind() == Kind.PROPERTY) { + mi.getStatic(owner, memInfo.getJavaName(), memInfo.getJavaDesc()); + } else { + mi.loadLocal(0); + mi.getField(owner, memInfo.getJavaName(), memInfo.getJavaDesc()); + } + mi.returnValue(); + mi.computeMaxs(); + mi.visitEnd(); + } + + static void addSetter(final ClassVisitor cv, final String owner, final MemberInfo memInfo) { + final int access = ACC_PUBLIC; + final String name = SETTER_PREFIX + memInfo.getJavaName(); + final String desc = setterDesc(memInfo); + final MethodVisitor mv = cv.visitMethod(access, name, desc, null, null); + final MethodGenerator mi = new MethodGenerator(mv, access, name, desc); + mi.visitCode(); + if (memInfo.isStatic() && memInfo.getKind() == Kind.PROPERTY) { + mi.loadLocal(1); + mi.putStatic(owner, memInfo.getJavaName(), memInfo.getJavaDesc()); + } else { + mi.loadLocal(0); + mi.loadLocal(1); + mi.putField(owner, memInfo.getJavaName(), memInfo.getJavaDesc()); + } + mi.returnVoid(); + mi.computeMaxs(); + mi.visitEnd(); + } + + static void addMapField(final ClassVisitor cv) { + // add a MAP static field + final FieldVisitor fv = cv.visitField(ACC_PRIVATE | ACC_STATIC, + MAP_FIELD_NAME, MAP_DESC, null, null); + if (fv != null) { + fv.visitEnd(); + } + } + + static void addField(final ClassVisitor cv, final String name, final String desc) { + final FieldVisitor fv = cv.visitField(ACC_PRIVATE, name, desc, null, null); + if (fv != null) { + fv.visitEnd(); + } + } + + static void addFunctionField(final ClassVisitor cv, final String name) { + addField(cv, name, OBJECT_DESC); + } + + static void newFunction(final MethodGenerator mi, final String className, final MemberInfo memInfo, final List<MemberInfo> specs) { + final boolean arityFound = (memInfo.getArity() != MemberInfo.DEFAULT_ARITY); + + mi.loadLiteral(memInfo.getName()); + mi.visitLdcInsn(new Handle(H_INVOKESTATIC, className, memInfo.getJavaName(), memInfo.getJavaDesc())); + + assert specs != null; + if (!specs.isEmpty()) { + mi.memberInfoArray(className, specs); + mi.invokeStatic(SCRIPTFUNCTIONIMPL_TYPE, SCRIPTFUNCTIONIMPL_MAKEFUNCTION, SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC); + } else { + mi.invokeStatic(SCRIPTFUNCTIONIMPL_TYPE, SCRIPTFUNCTIONIMPL_MAKEFUNCTION, SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC); + } + + if (arityFound) { + mi.dup(); + mi.push(memInfo.getArity()); + mi.invokeVirtual(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_SETARITY, SCRIPTFUNCTION_SETARITY_DESC); + } + + } + + static void linkerAddGetterSetter(final MethodGenerator mi, final String className, final MemberInfo memInfo) { + final String propertyName = memInfo.getName(); + mi.loadLocal(0); + mi.loadLiteral(propertyName); + // setup flags + mi.push(memInfo.getAttributes()); + // setup getter method handle + String javaName = GETTER_PREFIX + memInfo.getJavaName(); + mi.visitLdcInsn(new Handle(H_INVOKEVIRTUAL, className, javaName, getterDesc(memInfo))); + // setup setter method handle + if (memInfo.isFinal()) { + mi.pushNull(); + } else { + javaName = SETTER_PREFIX + memInfo.getJavaName(); + mi.visitLdcInsn(new Handle(H_INVOKEVIRTUAL, className, javaName, setterDesc(memInfo))); + } + mi.invokeStatic(LOOKUP_TYPE, LOOKUP_NEWPROPERTY, LOOKUP_NEWPROPERTY_DESC); + mi.storeLocal(0); + } + + static void linkerAddGetterSetter(final MethodGenerator mi, final String className, final MemberInfo getter, final MemberInfo setter) { + final String propertyName = getter.getName(); + mi.loadLocal(0); + mi.loadLiteral(propertyName); + // setup flags + mi.push(getter.getAttributes()); + // setup getter method handle + mi.visitLdcInsn(new Handle(H_INVOKESTATIC, className, + getter.getJavaName(), getter.getJavaDesc())); + // setup setter method handle + if (setter == null) { + mi.pushNull(); + } else { + mi.visitLdcInsn(new Handle(H_INVOKESTATIC, className, + setter.getJavaName(), setter.getJavaDesc())); + } + mi.invokeStatic(LOOKUP_TYPE, LOOKUP_NEWPROPERTY, LOOKUP_NEWPROPERTY_DESC); + mi.storeLocal(0); + } + + static ScriptClassInfo getScriptClassInfo(final String fileName) throws IOException { + try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fileName))) { + return getScriptClassInfo(new ClassReader(bis)); + } + } + + static ScriptClassInfo getScriptClassInfo(final byte[] classBuf) { + return getScriptClassInfo(new ClassReader(classBuf)); + } + + private static ScriptClassInfo getScriptClassInfo(final ClassReader reader) { + final ScriptClassInfoCollector scic = new ScriptClassInfoCollector(); + reader.accept(scic, 0); + return scic.getScriptClassInfo(); + } +} diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java new file mode 100644 index 00000000..2491e630 --- /dev/null +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.tools.nasgen; + +import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC; +import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER; +import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC; +import static jdk.internal.org.objectweb.asm.Opcodes.V1_7; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.CONSTRUCTOR_SUFFIX; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_DUPLICATE; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_DUPLICATE_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_FIELD_NAME; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_TYPE; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPE; +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_SETARITY; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_TYPE; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_INIT_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_TYPE; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.List; +import jdk.internal.org.objectweb.asm.Handle; + +/** + * This class generates constructor class for a @ClassInfo annotated class. + * + */ +public class ConstructorGenerator extends ClassGenerator { + private final ScriptClassInfo scriptClassInfo; + private final String className; + private final MemberInfo constructor; + private final int memberCount; + private final List<MemberInfo> specs; + + ConstructorGenerator(final ScriptClassInfo sci) { + this.scriptClassInfo = sci; + + this.className = scriptClassInfo.getConstructorClassName(); + this.constructor = scriptClassInfo.getConstructor(); + this.memberCount = scriptClassInfo.getConstructorMemberCount(); + this.specs = scriptClassInfo.getSpecializedConstructors(); + } + + byte[] getClassBytes() { + // new class extensing from ScriptObject + final String superClass = (constructor != null)? SCRIPTFUNCTIONIMPL_TYPE : SCRIPTOBJECT_TYPE; + cw.visit(V1_7, ACC_PUBLIC | ACC_SUPER, className, null, superClass, null); + if (memberCount > 0) { + // add fields + emitFields(); + // add <clinit> + emitStaticInitializer(); + } + // add <init> + emitConstructor(); + + if (constructor == null) { + emitGetClassName(scriptClassInfo.getName()); + } + + cw.visitEnd(); + return cw.toByteArray(); + } + + // --Internals only below this point + private void emitFields() { + // Introduce "Function" type instance fields for each + // constructor @Function in script class and introduce instance + // fields for each constructor @Property in the script class. + for (MemberInfo memInfo : scriptClassInfo.getMembers()) { + if (memInfo.isConstructorFunction()) { + addFunctionField(memInfo.getJavaName()); + memInfo = (MemberInfo)memInfo.clone(); + memInfo.setJavaDesc(OBJECT_DESC); + memInfo.setJavaAccess(ACC_PUBLIC); + addGetter(className, memInfo); + addSetter(className, memInfo); + } else if (memInfo.isConstructorProperty()) { + if (memInfo.isStaticFinal()) { + addGetter(scriptClassInfo.getJavaName(), memInfo); + } else { + addField(memInfo.getJavaName(), memInfo.getJavaDesc()); + memInfo = (MemberInfo)memInfo.clone(); + memInfo.setJavaAccess(ACC_PUBLIC); + addGetter(className, memInfo); + addSetter(className, memInfo); + } + } + } + + addMapField(); + } + + private void emitStaticInitializer() { + final MethodGenerator mi = makeStaticInitializer(); + emitStaticInitPrefix(mi, className); + + for (final MemberInfo memInfo : scriptClassInfo.getMembers()) { + if (memInfo.isConstructorFunction() || memInfo.isConstructorProperty()) { + linkerAddGetterSetter(mi, className, memInfo); + } else if (memInfo.isConstructorGetter()) { + final MemberInfo setter = scriptClassInfo.findSetter(memInfo); + linkerAddGetterSetter(mi, className, memInfo, setter); + } + } + emitStaticInitSuffix(mi, className); + } + + private void emitConstructor() { + final MethodGenerator mi = makeConstructor(); + mi.visitCode(); + callSuper(mi); + + if (memberCount > 0) { + // initialize Function type fields + initFunctionFields(mi); + // initialize data fields + initDataFields(mi); + } + + if (constructor != null) { + final int arity = constructor.getArity(); + if (arity != MemberInfo.DEFAULT_ARITY) { + mi.loadThis(); + mi.push(arity); + mi.invokeVirtual(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_SETARITY, + SCRIPTFUNCTION_SETARITY_DESC); + } + } + mi.returnVoid(); + mi.computeMaxs(); + mi.visitEnd(); + } + + private void loadMap(final MethodGenerator mi) { + if (memberCount > 0) { + mi.getStatic(className, MAP_FIELD_NAME, MAP_DESC); + // make sure we use duplicated PropertyMap so that original map + // stays intact and so can be used for many globals in same context + mi.invokeVirtual(MAP_TYPE, MAP_DUPLICATE, MAP_DUPLICATE_DESC); + } + } + + private void callSuper(final MethodGenerator mi) { + String superClass, superDesc; + mi.loadThis(); + if (constructor == null) { + // call ScriptObject.<init> + superClass = SCRIPTOBJECT_TYPE; + superDesc = (memberCount > 0) ? SCRIPTOBJECT_INIT_DESC : DEFAULT_INIT_DESC; + loadMap(mi); + } else { + // call Function.<init> + superClass = SCRIPTFUNCTIONIMPL_TYPE; + superDesc = (memberCount > 0) ? SCRIPTFUNCTIONIMPL_INIT_DESC4 : SCRIPTFUNCTIONIMPL_INIT_DESC3; + mi.loadLiteral(constructor.getName()); + mi.visitLdcInsn(new Handle(H_INVOKESTATIC, scriptClassInfo.getJavaName(), constructor.getJavaName(), constructor.getJavaDesc())); + loadMap(mi); + mi.memberInfoArray(scriptClassInfo.getJavaName(), specs); //pushes null if specs empty + } + + mi.invokeSpecial(superClass, INIT, superDesc); + } + + private void initFunctionFields(final MethodGenerator mi) { + for (final MemberInfo memInfo : scriptClassInfo.getMembers()) { + if (!memInfo.isConstructorFunction()) { + continue; + } + mi.loadThis(); + newFunction(mi, scriptClassInfo.getJavaName(), memInfo, scriptClassInfo.findSpecializations(memInfo.getJavaName())); + mi.putField(className, memInfo.getJavaName(), OBJECT_DESC); + } + } + + 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()); + } + } + + 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.putField(SCRIPTFUNCTION_TYPE, PROTOTYPE, OBJECT_DESC); + } + } + + /** + * Entry point for ConstructorGenerator run separately as an application. Will display + * usage. Takes one argument, a class name. + * @param args args vector + * @throws IOException if class can't be read + */ + public static void main(final String[] args) throws IOException { + if (args.length != 1) { + System.err.println("Usage: " + ConstructorGenerator.class.getName() + " <class>"); + System.exit(1); + } + + final String className = args[0].replace('.', '/'); + final ScriptClassInfo sci = getScriptClassInfo(className + ".class"); + if (sci == null) { + System.err.println("No @ScriptClass in " + className); + System.exit(2); + throw new IOException(); // get rid of warning for sci.verify() below - may be null + } + + try { + sci.verify(); + } catch (final Exception e) { + System.err.println(e.getMessage()); + System.exit(3); + } + final ConstructorGenerator gen = new ConstructorGenerator(sci); + try (FileOutputStream fos = new FileOutputStream(className + CONSTRUCTOR_SUFFIX + ".class")) { + fos.write(gen.getClassBytes()); + } + } +} diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/Main.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/Main.java new file mode 100644 index 00000000..96e49c1d --- /dev/null +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/Main.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.tools.nasgen; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import jdk.internal.org.objectweb.asm.ClassReader; +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.util.CheckClassAdapter; + +/** + * Main class for the "nasgen" tool. + * + */ +public class Main { + private static final boolean DEBUG = Boolean.getBoolean("nasgen.debug"); + + private interface ErrorReporter { + public void error(String msg); + } + + /** + * Public entry point for Nasgen if invoked from command line. Nasgen takes three arguments + * in order: input directory, package list, output directory + * + * @param args argument vector + */ + public static void main(final String[] args) { + final ErrorReporter reporter = new ErrorReporter() { + @Override + public void error(final String msg) { + Main.error(msg, 1); + } + }; + if (args.length == 3) { + processAll(args[0], args[1], args[2], reporter); + } else { + error("Usage: nasgen <input-dir> <package-list> <output-dir>", 1); + } + } + + private static void processAll(final String in, final String pkgList, final String out, final ErrorReporter reporter) { + final File inDir = new File(in); + if (!inDir.exists() || !inDir.isDirectory()) { + reporter.error(in + " does not exist or not a directory"); + return; + } + + final File outDir = new File(out); + if (!outDir.exists() || !outDir.isDirectory()) { + reporter.error(out + " does not exist or not a directory"); + return; + } + + final String[] packages = pkgList.split(":"); + for (String pkg : packages) { + pkg = pkg.replace('.', File.separatorChar); + final File dir = new File(inDir, pkg); + final File[] classes = dir.listFiles(); + for (final File clazz : classes) { + if (clazz.isFile() && clazz.getName().endsWith(".class")) { + if (! process(clazz, new File(outDir, pkg), reporter)) { + return; + } + } + } + } + } + + private static boolean process(final File inFile, final File outDir, final ErrorReporter reporter) { + try { + byte[] buf = new byte[(int)inFile.length()]; + + try (FileInputStream fin = new FileInputStream(inFile)) { + fin.read(buf); + } + + final ScriptClassInfo sci = ClassGenerator.getScriptClassInfo(buf); + + if (sci != null) { + try { + sci.verify(); + } catch (final Exception e) { + reporter.error(e.getMessage()); + return false; + } + + // create necessary output package dir + outDir.mkdirs(); + + // instrument @ScriptClass + final ClassWriter writer = ClassGenerator.makeClassWriter(); + final ClassReader reader = new ClassReader(buf); + final ScriptClassInstrumentor inst = new ScriptClassInstrumentor(writer, sci); + reader.accept(inst, 0); + //noinspection UnusedAssignment + + // write instrumented class + try (FileOutputStream fos = new FileOutputStream(new File(outDir, inFile.getName()))) { + buf = writer.toByteArray(); + if (DEBUG) { + verify(buf); + } + fos.write(buf); + } + + // simple class name without package prefix + String simpleName = inFile.getName(); + simpleName = simpleName.substring(0, simpleName.indexOf(".class")); + + if (sci.getPrototypeMemberCount() > 0) { + // generate prototype class + final PrototypeGenerator protGen = new PrototypeGenerator(sci); + buf = protGen.getClassBytes(); + if (DEBUG) { + verify(buf); + } + try (FileOutputStream fos = new FileOutputStream(new File(outDir, simpleName + StringConstants.PROTOTYPE_SUFFIX + ".class"))) { + fos.write(buf); + } + } + + if (sci.getConstructorMemberCount() > 0 || sci.getConstructor() != null) { + // generate constructor class + final ConstructorGenerator consGen = new ConstructorGenerator(sci); + buf = consGen.getClassBytes(); + if (DEBUG) { + verify(buf); + } + try (FileOutputStream fos = new FileOutputStream(new File(outDir, simpleName + StringConstants.CONSTRUCTOR_SUFFIX + ".class"))) { + fos.write(buf); + } + } + } + return true; + } catch (final IOException | RuntimeException e) { + if (DEBUG) { + e.printStackTrace(System.err); + } + reporter.error(e.getMessage()); + + return false; + } + } + + private static void verify(final byte[] buf) { + final ClassReader cr = new ClassReader(buf); + CheckClassAdapter.verify(cr, false, new PrintWriter(System.err)); + } + + private static void error(final String msg, final int exitCode) { + System.err.println(msg); + System.exit(exitCode); + } +} diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java new file mode 100644 index 00000000..62e8de2a --- /dev/null +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java @@ -0,0 +1,377 @@ +/* + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.tools.nasgen; + +import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_ARRAY_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC; + +import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.Type; +import jdk.nashorn.internal.objects.annotations.Where; + +/** + * Details about a Java method or field annotated with any of the field/method + * annotations from the jdk.nashorn.internal.objects.annotations package. + */ +public final class MemberInfo implements Cloneable { + /** + * The different kinds of available class annotations + */ + public static enum Kind { + /** This is a script class */ + SCRIPT_CLASS, + /** This is a constructor */ + CONSTRUCTOR, + /** This is a function */ + FUNCTION, + /** This is a getter */ + GETTER, + /** This is a setter */ + SETTER, + /** This is a property */ + PROPERTY, + /** This is a specialized version of a function */ + SPECIALIZED_FUNCTION, + /** This is a specialized version of a constructor */ + SPECIALIZED_CONSTRUCTOR + } + + // keep in sync with jdk.nashorn.internal.objects.annotations.Attribute + static final int DEFAULT_ATTRIBUTES = 0x0; + + static final int DEFAULT_ARITY = -2; + + // the kind of the script annotation - one of the above constants + private MemberInfo.Kind kind; + // script property name + private String name; + // script property attributes + private int attributes; + // name of the java member + private String javaName; + // type descriptor of the java member + private String javaDesc; + // access bits of the Java field or method + private int javaAccess; + // initial value for static @Property fields + private Object value; + // class whose object is created to fill property value + private String initClass; + // arity of the Function or Constructor + private int arity; + + private Where where; + + /** + * @return the kind + */ + public Kind getKind() { + return kind; + } + + /** + * @param kind the kind to set + */ + public void setKind(final Kind kind) { + this.kind = kind; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(final String name) { + this.name = name; + } + + /** + * @return the attributes + */ + public int getAttributes() { + return attributes; + } + + /** + * @param attributes the attributes to set + */ + public void setAttributes(final int attributes) { + this.attributes = attributes; + } + + /** + * @return the javaName + */ + public String getJavaName() { + return javaName; + } + + /** + * @param javaName the javaName to set + */ + public void setJavaName(final String javaName) { + this.javaName = javaName; + } + + /** + * @return the javaDesc + */ + public String getJavaDesc() { + return javaDesc; + } + + void setJavaDesc(final String javaDesc) { + this.javaDesc = javaDesc; + } + + int getJavaAccess() { + return javaAccess; + } + + void setJavaAccess(final int access) { + this.javaAccess = access; + } + + Object getValue() { + return value; + } + + void setValue(final Object value) { + this.value = value; + } + + Where getWhere() { + return where; + } + + void setWhere(final Where where) { + this.where = where; + } + + boolean isFinal() { + return (javaAccess & Opcodes.ACC_FINAL) != 0; + } + + boolean isStatic() { + return (javaAccess & Opcodes.ACC_STATIC) != 0; + } + + boolean isStaticFinal() { + return isStatic() && isFinal(); + } + + boolean isInstanceGetter() { + return kind == Kind.GETTER && where == Where.INSTANCE; + } + + /** + * Check whether this MemberInfo is a getter that resides in the instance + * @return true if instance setter + */ + boolean isInstanceSetter() { + return kind == Kind.SETTER && where == Where.INSTANCE; + } + + boolean isInstanceProperty() { + return kind == Kind.PROPERTY && where == Where.INSTANCE; + } + + boolean isInstanceFunction() { + return kind == Kind.FUNCTION && where == Where.INSTANCE; + } + + boolean isPrototypeGetter() { + return kind == Kind.GETTER && where == Where.PROTOTYPE; + } + + boolean isPrototypeSetter() { + return kind == Kind.SETTER && where == Where.PROTOTYPE; + } + + boolean isPrototypeProperty() { + return kind == Kind.PROPERTY && where == Where.PROTOTYPE; + } + + boolean isPrototypeFunction() { + return kind == Kind.FUNCTION && where == Where.PROTOTYPE; + } + + boolean isConstructorGetter() { + return kind == Kind.GETTER && where == Where.CONSTRUCTOR; + } + + boolean isConstructorSetter() { + return kind == Kind.SETTER && where == Where.CONSTRUCTOR; + } + + boolean isConstructorProperty() { + return kind == Kind.PROPERTY && where == Where.CONSTRUCTOR; + } + + boolean isConstructorFunction() { + return kind == Kind.FUNCTION && where == Where.CONSTRUCTOR; + } + + boolean isConstructor() { + return kind == Kind.CONSTRUCTOR; + } + + void verify() { + if (kind == Kind.CONSTRUCTOR) { + final Type returnType = Type.getReturnType(javaDesc); + if (! returnType.toString().equals(OBJECT_DESC)) { + error("return value should be of Object type, found" + returnType); + } + final Type[] argTypes = Type.getArgumentTypes(javaDesc); + if (argTypes.length < 2) { + error("constructor methods should have at least 2 args"); + } + if (! argTypes[0].equals(Type.BOOLEAN_TYPE)) { + error("first argument should be of boolean type, found" + argTypes[0]); + } + if (! argTypes[1].toString().equals(OBJECT_DESC)) { + error("second argument should be of Object type, found" + argTypes[0]); + } + + if (argTypes.length > 2) { + for (int i = 2; i < argTypes.length - 1; i++) { + if (! argTypes[i].toString().equals(OBJECT_DESC)) { + error(i + "'th argument should be of Object type, found " + argTypes[i]); + } + } + + final String lastArgType = argTypes[argTypes.length - 1].toString(); + final boolean isVarArg = lastArgType.equals(OBJECT_ARRAY_DESC); + if (!lastArgType.equals(OBJECT_DESC) && !isVarArg) { + error("last argument is neither Object nor Object[] type: " + lastArgType); + } + + if (isVarArg && argTypes.length > 3) { + error("vararg constructor has more than 3 arguments"); + } + } + } else if (kind == Kind.FUNCTION) { + final Type returnType = Type.getReturnType(javaDesc); + if (! returnType.toString().equals(OBJECT_DESC)) { + error("return value should be of Object type, found" + returnType); + } + final Type[] argTypes = Type.getArgumentTypes(javaDesc); + if (argTypes.length < 1) { + error("function methods should have at least 1 arg"); + } + if (! argTypes[0].toString().equals(OBJECT_DESC)) { + error("first argument should be of Object type, found" + argTypes[0]); + } + + if (argTypes.length > 1) { + for (int i = 1; i < argTypes.length - 1; i++) { + if (! argTypes[i].toString().equals(OBJECT_DESC)) { + error(i + "'th argument should be of Object type, found " + argTypes[i]); + } + } + + final String lastArgType = argTypes[argTypes.length - 1].toString(); + final boolean isVarArg = lastArgType.equals(OBJECT_ARRAY_DESC); + if (!lastArgType.equals(OBJECT_DESC) && !isVarArg) { + error("last argument is neither Object nor Object[] type: " + lastArgType); + } + + if (isVarArg && argTypes.length > 2) { + error("vararg function has more than 2 arguments"); + } + } + } else if (kind == Kind.GETTER) { + final Type[] argTypes = Type.getArgumentTypes(javaDesc); + if (argTypes.length != 1) { + error("getter methods should have one argument"); + } + if (! argTypes[0].toString().equals(OBJECT_DESC)) { + error("first argument of getter should be of Object type, found: " + argTypes[0]); + } + if (Type.getReturnType(javaDesc).equals(Type.VOID_TYPE)) { + error("return type of getter should not be void"); + } + } else if (kind == Kind.SETTER) { + final Type[] argTypes = Type.getArgumentTypes(javaDesc); + if (argTypes.length != 2) { + error("setter methods should have two arguments"); + } + if (! argTypes[0].toString().equals(OBJECT_DESC)) { + error("first argument of setter should be of Object type, found: " + argTypes[0]); + } + if (!Type.getReturnType(javaDesc).toString().equals("V")) { + error("return type of setter should be void, found: " + Type.getReturnType(javaDesc)); + } + } + } + + private void error(final String msg) { + throw new RuntimeException(javaName + javaDesc + " : " + msg); + } + + /** + * @return the initClass + */ + String getInitClass() { + return initClass; + } + + /** + * @param initClass the initClass to set + */ + void setInitClass(final String initClass) { + this.initClass = initClass; + } + + @Override + protected Object clone() { + try { + return super.clone(); + } catch (final CloneNotSupportedException e) { + assert false : "clone not supported " + e; + return null; + } + } + + /** + * @return the arity + */ + int getArity() { + return arity; + } + + /** + * @param arity the arity to set + */ + void setArity(final int arity) { + this.arity = arity; + } +} diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java new file mode 100644 index 00000000..500b8224 --- /dev/null +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java @@ -0,0 +1,426 @@ +/* + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.tools.nasgen; + +import static jdk.internal.org.objectweb.asm.Opcodes.AALOAD; +import static jdk.internal.org.objectweb.asm.Opcodes.AASTORE; +import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC; +import static jdk.internal.org.objectweb.asm.Opcodes.ACONST_NULL; +import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD; +import static jdk.internal.org.objectweb.asm.Opcodes.ANEWARRAY; +import static jdk.internal.org.objectweb.asm.Opcodes.ARETURN; +import static jdk.internal.org.objectweb.asm.Opcodes.ASM4; +import static jdk.internal.org.objectweb.asm.Opcodes.ASTORE; +import static jdk.internal.org.objectweb.asm.Opcodes.BALOAD; +import static jdk.internal.org.objectweb.asm.Opcodes.BASTORE; +import static jdk.internal.org.objectweb.asm.Opcodes.BIPUSH; +import static jdk.internal.org.objectweb.asm.Opcodes.CALOAD; +import static jdk.internal.org.objectweb.asm.Opcodes.CASTORE; +import static jdk.internal.org.objectweb.asm.Opcodes.CHECKCAST; +import static jdk.internal.org.objectweb.asm.Opcodes.DALOAD; +import static jdk.internal.org.objectweb.asm.Opcodes.DASTORE; +import static jdk.internal.org.objectweb.asm.Opcodes.DCONST_0; +import static jdk.internal.org.objectweb.asm.Opcodes.DRETURN; +import static jdk.internal.org.objectweb.asm.Opcodes.DUP; +import static jdk.internal.org.objectweb.asm.Opcodes.DUP2; +import static jdk.internal.org.objectweb.asm.Opcodes.FALOAD; +import static jdk.internal.org.objectweb.asm.Opcodes.FASTORE; +import static jdk.internal.org.objectweb.asm.Opcodes.FCONST_0; +import static jdk.internal.org.objectweb.asm.Opcodes.FRETURN; +import static jdk.internal.org.objectweb.asm.Opcodes.GETFIELD; +import static jdk.internal.org.objectweb.asm.Opcodes.GETSTATIC; +import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC; +import static jdk.internal.org.objectweb.asm.Opcodes.IALOAD; +import static jdk.internal.org.objectweb.asm.Opcodes.IASTORE; +import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_0; +import static jdk.internal.org.objectweb.asm.Opcodes.ILOAD; +import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL; +import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESTATIC; +import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEVIRTUAL; +import static jdk.internal.org.objectweb.asm.Opcodes.IRETURN; +import static jdk.internal.org.objectweb.asm.Opcodes.ISTORE; +import static jdk.internal.org.objectweb.asm.Opcodes.LALOAD; +import static jdk.internal.org.objectweb.asm.Opcodes.LASTORE; +import static jdk.internal.org.objectweb.asm.Opcodes.LCONST_0; +import static jdk.internal.org.objectweb.asm.Opcodes.LRETURN; +import static jdk.internal.org.objectweb.asm.Opcodes.NEW; +import static jdk.internal.org.objectweb.asm.Opcodes.POP; +import static jdk.internal.org.objectweb.asm.Opcodes.PUTFIELD; +import static jdk.internal.org.objectweb.asm.Opcodes.PUTSTATIC; +import static jdk.internal.org.objectweb.asm.Opcodes.RETURN; +import static jdk.internal.org.objectweb.asm.Opcodes.SALOAD; +import static jdk.internal.org.objectweb.asm.Opcodes.SASTORE; +import static jdk.internal.org.objectweb.asm.Opcodes.SIPUSH; +import static jdk.internal.org.objectweb.asm.Opcodes.SWAP; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.METHODHANDLE_TYPE; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.TYPE_METHODHANDLE; + +import java.util.List; +import jdk.internal.org.objectweb.asm.Handle; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Type; + +/** + * Base class for all method generating classes. + * + */ +public class MethodGenerator extends MethodVisitor { + private final int access; + private final String name; + private final String descriptor; + private final Type returnType; + private final Type[] argumentTypes; + + MethodGenerator(final MethodVisitor mv, final int access, final String name, final String descriptor) { + super(ASM4, mv); + this.access = access; + this.name = name; + this.descriptor = descriptor; + this.returnType = Type.getReturnType(descriptor); + this.argumentTypes = Type.getArgumentTypes(descriptor); + } + + int getAccess() { + return access; + } + + final String getName() { + return name; + } + + final String getDescriptor() { + return descriptor; + } + + final Type getReturnType() { + return returnType; + } + + final Type[] getArgumentTypes() { + return argumentTypes; + } + + /** + * Check whether access for this method is static + * @return true if static + */ + protected final boolean isStatic() { + return (getAccess() & ACC_STATIC) != 0; + } + + /** + * Check whether this method is a constructor + * @return true if constructor + */ + protected final boolean isConstructor() { + return "<init>".equals(name); + } + + void newObject(final String type) { + super.visitTypeInsn(NEW, type); + } + + void newObjectArray(final String type) { + super.visitTypeInsn(ANEWARRAY, type); + } + + void loadThis() { + if ((access & ACC_STATIC) != 0) { + throw new IllegalStateException("no 'this' inside static method"); + } + super.visitVarInsn(ALOAD, 0); + } + + void returnValue() { + super.visitInsn(returnType.getOpcode(IRETURN)); + } + + void returnVoid() { + super.visitInsn(RETURN); + } + + // load, store + void arrayLoad(final Type type) { + super.visitInsn(type.getOpcode(IALOAD)); + } + + void arrayLoad() { + super.visitInsn(AALOAD); + } + + void arrayStore(final Type type) { + super.visitInsn(type.getOpcode(IASTORE)); + } + + void arrayStore() { + super.visitInsn(AASTORE); + } + + void loadLiteral(final Object value) { + super.visitLdcInsn(value); + } + + void classLiteral(final String className) { + super.visitLdcInsn(className); + } + + void loadLocal(final Type type, final int index) { + super.visitVarInsn(type.getOpcode(ILOAD), index); + } + + void loadLocal(final int index) { + super.visitVarInsn(ALOAD, index); + } + + void storeLocal(final Type type, final int index) { + super.visitVarInsn(type.getOpcode(ISTORE), index); + } + + void storeLocal(final int index) { + super.visitVarInsn(ASTORE, index); + } + + void checkcast(final String type) { + super.visitTypeInsn(CHECKCAST, type); + } + + // push constants/literals + void pushNull() { + super.visitInsn(ACONST_NULL); + } + + void push(final int value) { + if (value >= -1 && value <= 5) { + super.visitInsn(ICONST_0 + value); + } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) { + super.visitIntInsn(BIPUSH, value); + } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) { + super.visitIntInsn(SIPUSH, value); + } else { + super.visitLdcInsn(value); + } + } + + void loadClass(final String className) { + super.visitLdcInsn(Type.getObjectType(className)); + } + + void pop() { + super.visitInsn(POP); + } + + // various "dups" + void dup() { + super.visitInsn(DUP); + } + + void dup2() { + super.visitInsn(DUP2); + } + + void swap() { + super.visitInsn(SWAP); + } + + void dupArrayValue(final int arrayOpcode) { + switch (arrayOpcode) { + case IALOAD: case FALOAD: + case AALOAD: case BALOAD: + case CALOAD: case SALOAD: + case IASTORE: case FASTORE: + case AASTORE: case BASTORE: + case CASTORE: case SASTORE: + dup(); + break; + + case LALOAD: case DALOAD: + case LASTORE: case DASTORE: + dup2(); + break; + default: + throw new AssertionError("invalid dup"); + } + } + + void dupReturnValue(final int returnOpcode) { + switch (returnOpcode) { + case IRETURN: + case FRETURN: + case ARETURN: + super.visitInsn(DUP); + return; + case LRETURN: + case DRETURN: + super.visitInsn(DUP2); + return; + case RETURN: + return; + default: + throw new IllegalArgumentException("not return"); + } + } + + void dupValue(final Type type) { + switch (type.getSize()) { + case 1: + dup(); + break; + case 2: + dup2(); + break; + default: + throw new AssertionError("invalid dup"); + } + } + + void dupValue(final String desc) { + final int typeCode = desc.charAt(0); + switch (typeCode) { + case '[': + case 'L': + case 'Z': + case 'C': + case 'B': + case 'S': + case 'I': + super.visitInsn(DUP); + break; + case 'J': + case 'D': + super.visitInsn(DUP2); + break; + default: + throw new RuntimeException("invalid signature"); + } + } + + // push default value of given type desc + void defaultValue(final String desc) { + final int typeCode = desc.charAt(0); + switch (typeCode) { + case '[': + case 'L': + super.visitInsn(ACONST_NULL); + break; + case 'Z': + case 'C': + case 'B': + case 'S': + case 'I': + super.visitInsn(ICONST_0); + break; + case 'J': + super.visitInsn(LCONST_0); + break; + case 'F': + super.visitInsn(FCONST_0); + break; + case 'D': + super.visitInsn(DCONST_0); + break; + default: + throw new AssertionError("invalid desc " + desc); + } + } + + // invokes, field get/sets + void invokeVirtual(final String owner, final String method, final String desc) { + super.visitMethodInsn(INVOKEVIRTUAL, owner, method, desc); + } + + void invokeSpecial(final String owner, final String method, final String desc) { + super.visitMethodInsn(INVOKESPECIAL, owner, method, desc); + } + + void invokeStatic(final String owner, final String method, final String desc) { + super.visitMethodInsn(INVOKESTATIC, owner, method, desc); + } + + void putStatic(final String owner, final String field, final String desc) { + super.visitFieldInsn(PUTSTATIC, owner, field, desc); + } + + void getStatic(final String owner, final String field, final String desc) { + super.visitFieldInsn(GETSTATIC, owner, field, desc); + } + + void putField(final String owner, final String field, final String desc) { + super.visitFieldInsn(PUTFIELD, owner, field, desc); + } + + void getField(final String owner, final String field, final String desc) { + super.visitFieldInsn(GETFIELD, owner, field, desc); + } + + void memberInfoArray(final String className, final List<MemberInfo> mis) { + if (mis.isEmpty()) { + pushNull(); + return; + } + + int pos = 0; + push(mis.size()); + newObjectArray(METHODHANDLE_TYPE); + for (final MemberInfo mi : mis) { + dup(); + push(pos++); + visitLdcInsn(new Handle(H_INVOKESTATIC, className, mi.getJavaName(), mi.getJavaDesc())); + arrayStore(TYPE_METHODHANDLE); + } + } + + void computeMaxs() { + // These values are ignored as we create class writer + // with ClassWriter.COMPUTE_MAXS flag. + super.visitMaxs(Short.MAX_VALUE, Short.MAX_VALUE); + } + + // debugging support - print calls + void println(final String msg) { + super.visitFieldInsn(GETSTATIC, + "java/lang/System", + "out", + "Ljava/io/PrintStream;"); + super.visitLdcInsn(msg); + super.visitMethodInsn(INVOKEVIRTUAL, + "java/io/PrintStream", + "println", + "(Ljava/lang/String;)V"); + } + + // print the object on the top of the stack + void printObject() { + super.visitFieldInsn(GETSTATIC, + "java/lang/System", + "out", + "Ljava/io/PrintStream;"); + super.visitInsn(SWAP); + super.visitMethodInsn(INVOKEVIRTUAL, + "java/io/PrintStream", + "println", + "(Ljava/lang/Object;)V"); + } +} diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/NullVisitor.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/NullVisitor.java new file mode 100644 index 00000000..7f585c03 --- /dev/null +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/NullVisitor.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.tools.nasgen; + +import jdk.internal.org.objectweb.asm.AnnotationVisitor; +import jdk.internal.org.objectweb.asm.ClassVisitor; +import jdk.internal.org.objectweb.asm.FieldVisitor; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; + +/** + * A visitor that does nothing on visitXXX calls. + * + */ +public class NullVisitor extends ClassVisitor { + NullVisitor() { + super(Opcodes.ASM4); + } + + @Override + public MethodVisitor visitMethod( + final int access, + final String name, + final String desc, + final String signature, + final String[] exceptions) { + return new MethodVisitor(Opcodes.ASM4) { + @Override + public AnnotationVisitor visitAnnotationDefault() { + return new NullAnnotationVisitor(); + } + + @Override + public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { + return new NullAnnotationVisitor(); + } + }; + } + + @Override + public FieldVisitor visitField( + final int access, + final String name, + final String desc, + final String signature, + final Object value) { + return new FieldVisitor(Opcodes.ASM4) { + @Override + public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { + return new NullAnnotationVisitor(); + } + }; + } + + @Override + public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { + return new NullAnnotationVisitor(); + } + + private static class NullAnnotationVisitor extends AnnotationVisitor { + NullAnnotationVisitor() { + super(Opcodes.ASM4); + } + } +} diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java new file mode 100644 index 00000000..a8b6e639 --- /dev/null +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.tools.nasgen; + +import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC; +import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER; +import static jdk.internal.org.objectweb.asm.Opcodes.V1_7; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_DUPLICATE; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_DUPLICATE_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_FIELD_NAME; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_TYPE; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_TYPE; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPE_SUFFIX; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_INIT_DESC; + +import java.io.FileOutputStream; +import java.io.IOException; + +/** + * This class generates prototype class for a @ClassInfo annotated class. + * + */ +public class PrototypeGenerator extends ClassGenerator { + private final ScriptClassInfo scriptClassInfo; + private final String className; + private final int memberCount; + + PrototypeGenerator(final ScriptClassInfo sci) { + this.scriptClassInfo = sci; + this.className = scriptClassInfo.getPrototypeClassName(); + this.memberCount = scriptClassInfo.getPrototypeMemberCount(); + } + + byte[] getClassBytes() { + // new class extensing from ScriptObject + cw.visit(V1_7, ACC_PUBLIC | ACC_SUPER, className, null, PROTOTYPEOBJECT_TYPE, null); + if (memberCount > 0) { + // add fields + emitFields(); + // add <clinit> + emitStaticInitializer(); + } + // add <init> + emitConstructor(); + + // add getClassName() + emitGetClassName(scriptClassInfo.getName()); + + cw.visitEnd(); + return cw.toByteArray(); + } + + // --Internals only below this point + private void emitFields() { + // introduce "Function" type instance fields for each + // prototype @Function in script class info + for (MemberInfo memInfo : scriptClassInfo.getMembers()) { + if (memInfo.isPrototypeFunction()) { + addFunctionField(memInfo.getJavaName()); + memInfo = (MemberInfo)memInfo.clone(); + memInfo.setJavaDesc(OBJECT_DESC); + addGetter(className, memInfo); + addSetter(className, memInfo); + } else if (memInfo.isPrototypeProperty()) { + if (memInfo.isStaticFinal()) { + addGetter(scriptClassInfo.getJavaName(), memInfo); + } else { + addField(memInfo.getJavaName(), memInfo.getJavaDesc()); + memInfo = (MemberInfo)memInfo.clone(); + memInfo.setJavaAccess(ACC_PUBLIC); + addGetter(className, memInfo); + addSetter(className, memInfo); + } + } + } + + addMapField(); + } + + private void emitStaticInitializer() { + final MethodGenerator mi = makeStaticInitializer(); + emitStaticInitPrefix(mi, className); + for (final MemberInfo memInfo : scriptClassInfo.getMembers()) { + if (memInfo.isPrototypeFunction() || memInfo.isPrototypeProperty()) { + linkerAddGetterSetter(mi, className, memInfo); + } else if (memInfo.isPrototypeGetter()) { + final MemberInfo setter = scriptClassInfo.findSetter(memInfo); + linkerAddGetterSetter(mi, className, memInfo, setter); + } + } + emitStaticInitSuffix(mi, className); + } + + private void emitConstructor() { + final MethodGenerator mi = makeConstructor(); + mi.visitCode(); + mi.loadThis(); + if (memberCount > 0) { + // call "super(map$)" + mi.getStatic(className, MAP_FIELD_NAME, MAP_DESC); + // make sure we use duplicated PropertyMap so that original map + // stays intact and so can be used for many globals in same context + mi.invokeVirtual(MAP_TYPE, MAP_DUPLICATE, MAP_DUPLICATE_DESC); + mi.invokeSpecial(PROTOTYPEOBJECT_TYPE, INIT, SCRIPTOBJECT_INIT_DESC); + // initialize Function type fields + initFunctionFields(mi); + } else { + // call "super()" + mi.invokeSpecial(PROTOTYPEOBJECT_TYPE, INIT, DEFAULT_INIT_DESC); + } + mi.returnVoid(); + mi.computeMaxs(); + mi.visitEnd(); + } + + private void initFunctionFields(final MethodGenerator mi) { + for (final MemberInfo memInfo : scriptClassInfo.getMembers()) { + if (! memInfo.isPrototypeFunction()) { + continue; + } + mi.loadThis(); + newFunction(mi, scriptClassInfo.getJavaName(), memInfo, scriptClassInfo.findSpecializations(memInfo.getJavaName())); + mi.putField(className, memInfo.getJavaName(), OBJECT_DESC); + } + } + + /** + * External entry point for PrototypeGenerator if called from the command line + * + * @param args arguments, takes 1 argument which is the class to process + * @throws IOException if class cannot be read + */ + public static void main(final String[] args) throws IOException { + if (args.length != 1) { + System.err.println("Usage: " + ConstructorGenerator.class.getName() + " <class>"); + System.exit(1); + } + + final String className = args[0].replace('.', '/'); + final ScriptClassInfo sci = getScriptClassInfo(className + ".class"); + if (sci == null) { + System.err.println("No @ScriptClass in " + className); + System.exit(2); + throw new AssertionError(); //guard against warning that sci is null below + } + try { + sci.verify(); + } catch (final Exception e) { + System.err.println(e.getMessage()); + System.exit(3); + } + final PrototypeGenerator gen = new PrototypeGenerator(sci); + try (FileOutputStream fos = new FileOutputStream(className + PROTOTYPE_SUFFIX + ".class")) { + fos.write(gen.getClassBytes()); + } + } +} diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java new file mode 100644 index 00000000..b5e28522 --- /dev/null +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.tools.nasgen; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import jdk.internal.org.objectweb.asm.Type; +import jdk.nashorn.internal.objects.annotations.Constructor; +import jdk.nashorn.internal.objects.annotations.Function; +import jdk.nashorn.internal.objects.annotations.Getter; +import jdk.nashorn.internal.objects.annotations.Property; +import jdk.nashorn.internal.objects.annotations.ScriptClass; +import jdk.nashorn.internal.objects.annotations.Setter; +import jdk.nashorn.internal.objects.annotations.SpecializedConstructor; +import jdk.nashorn.internal.objects.annotations.SpecializedFunction; +import jdk.nashorn.internal.objects.annotations.Where; +import jdk.nashorn.internal.tools.nasgen.MemberInfo.Kind; + +/** + * All annotation information from a class that is annotated with + * the annotation com.sun.oracle.objects.annotations.ScriptClass. + * + */ +public final class ScriptClassInfo { + // descriptots 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); + static final String GETTER_ANNO_DESC = Type.getDescriptor(Getter.class); + static final String SETTER_ANNO_DESC = Type.getDescriptor(Setter.class); + static final String PROPERTY_ANNO_DESC = Type.getDescriptor(Property.class); + static final String WHERE_ENUM_DESC = Type.getDescriptor(Where.class); + static final String SPECIALIZED_FUNCTION = Type.getDescriptor(SpecializedFunction.class); + static final String SPECIALIZED_CONSTRUCTOR = Type.getDescriptor(SpecializedConstructor.class); + + static final Map<String, Kind> annotations = new HashMap<>(); + + static { + annotations.put(SCRIPT_CLASS_ANNO_DESC, Kind.SCRIPT_CLASS); + annotations.put(FUNCTION_ANNO_DESC, Kind.FUNCTION); + annotations.put(CONSTRUCTOR_ANNO_DESC, Kind.CONSTRUCTOR); + annotations.put(GETTER_ANNO_DESC, Kind.GETTER); + annotations.put(SETTER_ANNO_DESC, Kind.SETTER); + annotations.put(PROPERTY_ANNO_DESC, Kind.PROPERTY); + annotations.put(SPECIALIZED_FUNCTION, Kind.SPECIALIZED_FUNCTION); + annotations.put(SPECIALIZED_CONSTRUCTOR, Kind.SPECIALIZED_CONSTRUCTOR); + } + + // name of the script class + private String name; + // member info for script properties + private List<MemberInfo> members = Collections.emptyList(); + // java class name that is annotated with @ScriptClass + private String javaName; + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(final String name) { + this.name = name; + } + + /** + * @return the members + */ + public List<MemberInfo> getMembers() { + return Collections.unmodifiableList(members); + } + + /** + * @param members the members to set + */ + public void setMembers(final List<MemberInfo> members) { + this.members = members; + } + + MemberInfo getConstructor() { + for (final MemberInfo memInfo : members) { + if (memInfo.getKind() == Kind.CONSTRUCTOR) { + return memInfo; + } + } + return null; + } + + List<MemberInfo> getSpecializedConstructors() { + final List<MemberInfo> res = new LinkedList<>(); + for (final MemberInfo memInfo : members) { + if (memInfo.getKind() == Kind.SPECIALIZED_CONSTRUCTOR) { + res.add(memInfo); + } + } + return res; + } + + int getPrototypeMemberCount() { + int count = 0; + for (final MemberInfo memInfo : members) { + if (memInfo.getWhere() == Where.PROTOTYPE || memInfo.isConstructor()) { + count++; + } + } + return count; + } + + int getConstructorMemberCount() { + int count = 0; + for (final MemberInfo memInfo : members) { + if (memInfo.getWhere() == Where.CONSTRUCTOR) { + count++; + } + } + return count; + } + + int getInstancePropertyCount() { + int count = 0; + for (final MemberInfo memInfo : members) { + if (memInfo.getWhere() == Where.INSTANCE) { + count++; + } + } + return count; + } + + MemberInfo find(final String findJavaName, final String findJavaDesc, final int findAccess) { + for (final MemberInfo memInfo : members) { + if (memInfo.getJavaName().equals(findJavaName) && + memInfo.getJavaDesc().equals(findJavaDesc) && + memInfo.getJavaAccess() == findAccess) { + return memInfo; + } + } + return null; + } + + List<MemberInfo> findSpecializations(final String methodName) { + final List<MemberInfo> res = new LinkedList<>(); + for (final MemberInfo memInfo : members) { + if (memInfo.getName().equals(methodName) && + memInfo.getKind() == Kind.SPECIALIZED_FUNCTION) { + res.add(memInfo); + } + } + return res; + } + + MemberInfo findSetter(final MemberInfo getter) { + assert getter.getKind() == Kind.GETTER : "getter expected"; + final String getterName = getter.getName(); + final Where getterWhere = getter.getWhere(); + for (final MemberInfo memInfo : members) { + if (memInfo.getKind() == Kind.SETTER && + getterName.equals(memInfo.getName()) && + getterWhere == memInfo.getWhere()) { + return memInfo; + } + } + return null; + } + + /** + * @return the javaName + */ + public String getJavaName() { + return javaName; + } + + /** + * @param javaName the javaName to set + */ + void setJavaName(final String javaName) { + this.javaName = javaName; + } + + String getConstructorClassName() { + return getJavaName() + StringConstants.CONSTRUCTOR_SUFFIX; + } + + String getPrototypeClassName() { + return getJavaName() + StringConstants.PROTOTYPE_SUFFIX; + } + + void verify() { + boolean constructorSeen = false; + for (final MemberInfo memInfo : getMembers()) { + if (memInfo.isConstructor()) { + if (constructorSeen) { + error("more than @Constructor method"); + } + constructorSeen = true; + } + try { + memInfo.verify(); + } catch (final Exception e) { + error(e.getMessage()); + } + } + } + + private void error(final String msg) throws RuntimeException { + throw new RuntimeException(javaName + " : " + msg); + } +} diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java new file mode 100644 index 00000000..43c2bc6c --- /dev/null +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.tools.nasgen; + +import static jdk.nashorn.internal.tools.nasgen.ScriptClassInfo.SCRIPT_CLASS_ANNO_DESC; +import static jdk.nashorn.internal.tools.nasgen.ScriptClassInfo.WHERE_ENUM_DESC; + +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import jdk.internal.org.objectweb.asm.AnnotationVisitor; +import jdk.internal.org.objectweb.asm.ClassReader; +import jdk.internal.org.objectweb.asm.ClassVisitor; +import jdk.internal.org.objectweb.asm.FieldVisitor; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.nashorn.internal.objects.annotations.Where; +import jdk.nashorn.internal.tools.nasgen.MemberInfo.Kind; + +/** + * This class collects all @ScriptClass and other annotation information from a + * compiled .class file. Enforces that @Function/@Getter/@Setter/@Constructor + * methods are declared to be 'static'. + */ +public class ScriptClassInfoCollector extends ClassVisitor { + private String scriptClassName; + private List<MemberInfo> scriptMembers; + private String javaClassName; + + ScriptClassInfoCollector(final ClassVisitor visitor) { + super(Opcodes.ASM4, visitor); + } + + ScriptClassInfoCollector() { + this(new NullVisitor()); + } + + private void addScriptMember(final MemberInfo memInfo) { + if (scriptMembers == null) { + scriptMembers = new ArrayList<>(); + } + scriptMembers.add(memInfo); + } + + @Override + public void visit(final int version, final int access, final String name, final String signature, + final String superName, final String[] interfaces) { + super.visit(version, access, name, signature, superName, interfaces); + javaClassName = name; + } + + @Override + public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { + final AnnotationVisitor delegateAV = super.visitAnnotation(desc, visible); + if (SCRIPT_CLASS_ANNO_DESC.equals(desc)) { + return new AnnotationVisitor(Opcodes.ASM4, delegateAV) { + @Override + public void visit(final String name, final Object value) { + if ("value".equals(name)) { + scriptClassName = (String) value; + } + super.visit(name, value); + } + }; + } + + return delegateAV; + } + + @Override + public FieldVisitor visitField(final int fieldAccess, final String fieldName, final String fieldDesc, final String signature, final Object value) { + final FieldVisitor delegateFV = super.visitField(fieldAccess, fieldName, fieldDesc, signature, value); + + return new FieldVisitor(Opcodes.ASM4, delegateFV) { + @Override + public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { + final AnnotationVisitor delegateAV = super.visitAnnotation(descriptor, visible); + + if (ScriptClassInfo.PROPERTY_ANNO_DESC.equals(descriptor)) { + final MemberInfo memInfo = new MemberInfo(); + + memInfo.setKind(Kind.PROPERTY); + memInfo.setJavaName(fieldName); + memInfo.setJavaDesc(fieldDesc); + memInfo.setJavaAccess(fieldAccess); + + if ((fieldAccess & Opcodes.ACC_STATIC) != 0) { + memInfo.setValue(value); + } + + addScriptMember(memInfo); + + return new AnnotationVisitor(Opcodes.ASM4, delegateAV) { + // These could be "null" if values are not suppiled, + // in which case we have to use the default values. + private String name; + private Integer attributes; + private String clazz = ""; + private Where where; + + @Override + public void visit(final String annotationName, final Object annotationValue) { + switch (annotationName) { + case "name": + this.name = (String) annotationValue; + break; + case "attributes": + this.attributes = (Integer) annotationValue; + break; + case "clazz": + this.clazz = (annotationValue == null) ? "" : annotationValue.toString(); + break; + default: + break; + } + super.visit(annotationName, annotationValue); + } + + @Override + public void visitEnum(final String enumName, final String desc, final String enumValue) { + if ("where".equals(enumName) && WHERE_ENUM_DESC.equals(desc)) { + this.where = Where.valueOf(enumValue); + } + super.visitEnum(enumName, desc, enumValue); + } + + @Override + public void visitEnd() { + super.visitEnd(); + memInfo.setName(name == null ? fieldName : name); + memInfo.setAttributes(attributes == null + ? MemberInfo.DEFAULT_ATTRIBUTES : attributes); + clazz = clazz.replace('.', '/'); + memInfo.setInitClass(clazz); + memInfo.setWhere(where == null? Where.INSTANCE : where); + } + }; + } + + return delegateAV; + } + }; + } + + private void error(final String javaName, final String javaDesc, final String msg) { + throw new RuntimeException(scriptClassName + "." + javaName + javaDesc + " : " + msg); + } + + @Override + public MethodVisitor visitMethod(final int methodAccess, final String methodName, + final String methodDesc, final String signature, final String[] exceptions) { + + final MethodVisitor delegateMV = super.visitMethod(methodAccess, methodName, methodDesc, + signature, exceptions); + + return new MethodVisitor(Opcodes.ASM4, delegateMV) { + + @Override + public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { + final AnnotationVisitor delegateAV = super.visitAnnotation(descriptor, visible); + final Kind annoKind = ScriptClassInfo.annotations.get(descriptor); + + if (annoKind != null) { + if ((methodAccess & Opcodes.ACC_STATIC) == 0) { + error(methodName, methodDesc, "nasgen method annotations cannot be on instance methods"); + } + + final MemberInfo memInfo = new MemberInfo(); + + memInfo.setKind(annoKind); + memInfo.setJavaName(methodName); + memInfo.setJavaDesc(methodDesc); + memInfo.setJavaAccess(methodAccess); + + addScriptMember(memInfo); + + return new AnnotationVisitor(Opcodes.ASM4, delegateAV) { + // These could be "null" if values are not suppiled, + // in which case we have to use the default values. + private String name; + private Integer attributes; + private Integer arity; + private Where where; + + @Override + public void visit(final String annotationName, final Object annotationValue) { + switch (annotationName) { + case "name": + this.name = (String)annotationValue; + break; + case "attributes": + this.attributes = (Integer)annotationValue; + break; + case "arity": + this.arity = (Integer)annotationValue; + break; + default: + break; + } + + super.visit(annotationName, annotationValue); + } + + @Override + public void visitEnum(final String enumName, final String desc, final String enumValue) { + if ("where".equals(enumName) && WHERE_ENUM_DESC.equals(desc)) { + this.where = Where.valueOf(enumValue); + } + super.visitEnum(enumName, desc, enumValue); + } + + @Override + public void visitEnd() { + super.visitEnd(); + + if (memInfo.getKind() == Kind.CONSTRUCTOR) { + memInfo.setName(name == null ? scriptClassName : name); + } else { + memInfo.setName(name == null ? methodName : name); + } + memInfo.setAttributes(attributes == null ? MemberInfo.DEFAULT_ATTRIBUTES : attributes); + + memInfo.setArity((arity == null)? MemberInfo.DEFAULT_ARITY : arity); + if (where == null) { + // by default @Getter/@Setter belongs to INSTANCE + // @Function belong to PROTOTYPE. + switch (memInfo.getKind()) { + case GETTER: + case SETTER: + where = Where.INSTANCE; + break; + case SPECIALIZED_CONSTRUCTOR: + case CONSTRUCTOR: + where = Where.CONSTRUCTOR; + break; + case FUNCTION: + where = Where.PROTOTYPE; + break; + case SPECIALIZED_FUNCTION: + //TODO is this correct + default: + break; + } + } + memInfo.setWhere(where); + } + }; + } + + return delegateAV; + } + }; + } + + ScriptClassInfo getScriptClassInfo() { + ScriptClassInfo sci = null; + if (scriptClassName != null) { + sci = new ScriptClassInfo(); + sci.setName(scriptClassName); + if (scriptMembers == null) { + scriptMembers = Collections.emptyList(); + } + sci.setMembers(scriptMembers); + sci.setJavaName(javaClassName); + } + return sci; + } + + /** + * External entry point for ScriptClassInfoCollector if invoked from the command line + * @param args argument vector, args contains a class for which to collect info + * @throws IOException if there were problems parsing args or class + */ + public static void main(final String[] args) throws IOException { + if (args.length != 1) { + System.err.println("Usage: " + ScriptClassInfoCollector.class.getName() + " <class>"); + System.exit(1); + } + + args[0] = args[0].replace('.', '/'); + final ScriptClassInfoCollector scic = new ScriptClassInfoCollector(); + try (final BufferedInputStream bis = new BufferedInputStream(new FileInputStream(args[0] + ".class"))) { + final ClassReader reader = new ClassReader(bis); + reader.accept(scic, 0); + } + final ScriptClassInfo sci = scic.getScriptClassInfo(); + final PrintStream out = System.out; + if (sci != null) { + out.println("script class: " + sci.getName()); + out.println("==================================="); + for (final MemberInfo memInfo : sci.getMembers()) { + out.println("kind : " + memInfo.getKind()); + out.println("name : " + memInfo.getName()); + out.println("attributes: " + memInfo.getAttributes()); + out.println("javaName: " + memInfo.getJavaName()); + out.println("javaDesc: " + memInfo.getJavaDesc()); + out.println("where: " + memInfo.getWhere()); + out.println("====================================="); + } + } else { + out.println(args[0] + " is not a @ScriptClass"); + } + } +} diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java new file mode 100644 index 00000000..c8e97370 --- /dev/null +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.tools.nasgen; + +import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD; +import static jdk.internal.org.objectweb.asm.Opcodes.DUP; +import static jdk.internal.org.objectweb.asm.Opcodes.GETSTATIC; +import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL; +import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESTATIC; +import static jdk.internal.org.objectweb.asm.Opcodes.NEW; +import static jdk.internal.org.objectweb.asm.Opcodes.PUTFIELD; +import static jdk.internal.org.objectweb.asm.Opcodes.RETURN; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.$CLINIT$; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.CLINIT; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.DEFAULT_INIT_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.INIT; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.MAP_FIELD_NAME; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.OBJECT_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_INIT_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTOBJECT_TYPE; + +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import jdk.internal.org.objectweb.asm.AnnotationVisitor; +import jdk.internal.org.objectweb.asm.Attribute; +import jdk.internal.org.objectweb.asm.ClassReader; +import jdk.internal.org.objectweb.asm.ClassVisitor; +import jdk.internal.org.objectweb.asm.ClassWriter; +import jdk.internal.org.objectweb.asm.FieldVisitor; +import jdk.internal.org.objectweb.asm.MethodVisitor; +import jdk.internal.org.objectweb.asm.Opcodes; +import jdk.internal.org.objectweb.asm.util.CheckClassAdapter; +import jdk.nashorn.internal.objects.annotations.Where; +import jdk.nashorn.internal.tools.nasgen.MemberInfo.Kind; + +/** + * This class instruments the java class annotated with @ScriptClass. + * + * Changes done are: + * + * 1) remove all jdk.nashorn.internal.objects.annotations.* annotations. + * 2) static final @Property fields stay here. Other @Property fields moved to + * respective classes depending on 'where' value of annotation. + * 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; + private boolean staticInitFound; + + ScriptClassInstrumentor(final ClassVisitor visitor, final ScriptClassInfo sci) { + super(Opcodes.ASM4, visitor); + if (sci == null) { + throw new IllegalArgumentException("Null ScriptClassInfo, is the class annotated?"); + } + this.scriptClassInfo = sci; + this.memberCount = scriptClassInfo.getInstancePropertyCount(); + } + + @Override + public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { + if (ScriptClassInfo.annotations.containsKey(desc)) { + // ignore @ScriptClass + return null; + } + + return super.visitAnnotation(desc, visible); + } + + @Override + public FieldVisitor visitField(final int fieldAccess, final String fieldName, + final String fieldDesc, final String signature, final Object value) { + final MemberInfo memInfo = scriptClassInfo.find(fieldName, fieldDesc, fieldAccess); + if (memInfo != null && memInfo.getKind() == Kind.PROPERTY && + memInfo.getWhere() != Where.INSTANCE && !memInfo.isStaticFinal()) { + // non-instance @Property fields - these have to go elsewhere unless 'static final' + return null; + } + + final FieldVisitor delegateFV = super.visitField(fieldAccess, fieldName, fieldDesc, + signature, value); + return new FieldVisitor(Opcodes.ASM4, delegateFV) { + @Override + public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { + if (ScriptClassInfo.annotations.containsKey(desc)) { + // ignore script field annotations + return null; + } + + return fv.visitAnnotation(desc, visible); + } + + @Override + public void visitAttribute(final Attribute attr) { + fv.visitAttribute(attr); + } + + @Override + public void visitEnd() { + fv.visitEnd(); + } + }; + } + + @Override + public MethodVisitor visitMethod(final int methodAccess, final String methodName, + final String methodDesc, final String signature, final String[] exceptions) { + + final boolean isConstructor = INIT.equals(methodName); + final boolean isStaticInit = CLINIT.equals(methodName); + + if (isStaticInit) { + staticInitFound = true; + } + + final MethodGenerator delegateMV = new MethodGenerator(super.visitMethod(methodAccess, methodName, methodDesc, + signature, exceptions), methodAccess, methodName, methodDesc); + + return new MethodVisitor(Opcodes.ASM4, delegateMV) { + @Override + public void visitInsn(final int opcode) { + // call $clinit$ just before return from <clinit> + if (isStaticInit && opcode == RETURN) { + super.visitMethodInsn(INVOKESTATIC, scriptClassInfo.getJavaName(), + $CLINIT$, DEFAULT_INIT_DESC); + } + super.visitInsn(opcode); + } + + @Override + public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) { + if (isConstructor && opcode == INVOKESPECIAL && + INIT.equals(name) && SCRIPTOBJECT_TYPE.equals(owner)) { + super.visitFieldInsn(GETSTATIC, scriptClassInfo.getJavaName(), + MAP_FIELD_NAME, MAP_DESC); + super.visitMethodInsn(INVOKESPECIAL, SCRIPTOBJECT_TYPE, INIT, + SCRIPTOBJECT_INIT_DESC); + + if (memberCount > 0) { + // initialize @Property fields if needed + for (final MemberInfo memInfo : scriptClassInfo.getMembers()) { + if (memInfo.isInstanceProperty() && !memInfo.getInitClass().isEmpty()) { + final String clazz = memInfo.getInitClass(); + super.visitVarInsn(ALOAD, 0); + super.visitTypeInsn(NEW, clazz); + super.visitInsn(DUP); + super.visitMethodInsn(INVOKESPECIAL, clazz, + INIT, DEFAULT_INIT_DESC); + super.visitFieldInsn(PUTFIELD, scriptClassInfo.getJavaName(), + memInfo.getJavaName(), memInfo.getJavaDesc()); + } + + if (memInfo.isInstanceFunction()) { + super.visitVarInsn(ALOAD, 0); + ClassGenerator.newFunction(delegateMV, scriptClassInfo.getJavaName(), memInfo, scriptClassInfo.findSpecializations(memInfo.getJavaName())); + super.visitFieldInsn(PUTFIELD, scriptClassInfo.getJavaName(), + memInfo.getJavaName(), OBJECT_DESC); + } + } + } + } else { + super.visitMethodInsn(opcode, owner, name, desc); + } + } + + @Override + public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) { + if (ScriptClassInfo.annotations.containsKey(desc)) { + // ignore script method annotations + return null; + } + return super.visitAnnotation(desc, visible); + } + }; + } + + @Override + public void visitEnd() { + emitFields(); + emitStaticInitializer(); + emitGettersSetters(); + super.visitEnd(); + } + + private void emitFields() { + // introduce "Function" type instance fields for each + // instance @Function in script class info + final String className = scriptClassInfo.getJavaName(); + for (MemberInfo memInfo : scriptClassInfo.getMembers()) { + if (memInfo.isInstanceFunction()) { + ClassGenerator.addFunctionField(cv, memInfo.getJavaName()); + memInfo = (MemberInfo)memInfo.clone(); + memInfo.setJavaDesc(OBJECT_DESC); + ClassGenerator.addGetter(cv, className, memInfo); + ClassGenerator.addSetter(cv, className, memInfo); + } + } + ClassGenerator.addMapField(this); + } + + void emitGettersSetters() { + if (memberCount > 0) { + for (final MemberInfo memInfo : scriptClassInfo.getMembers()) { + final String className = scriptClassInfo.getJavaName(); + if (memInfo.isInstanceProperty()) { + ClassGenerator.addGetter(cv, className, memInfo); + if (! memInfo.isFinal()) { + ClassGenerator.addSetter(cv, className, memInfo); + } + } + } + } + } + + private void emitStaticInitializer() { + final String className = scriptClassInfo.getJavaName(); + if (! staticInitFound) { + // no user written <clinit> and so create one + final MethodVisitor mv = ClassGenerator.makeStaticInitializer(this); + mv.visitCode(); + mv.visitInsn(RETURN); + mv.visitMaxs(Short.MAX_VALUE, 0); + mv.visitEnd(); + } + // Now generate $clinit$ + final MethodGenerator mi = ClassGenerator.makeStaticInitializer(this, $CLINIT$); + ClassGenerator.emitStaticInitPrefix(mi, className); + if (memberCount > 0) { + for (final MemberInfo memInfo : scriptClassInfo.getMembers()) { + if (memInfo.isInstanceProperty() || memInfo.isInstanceFunction()) { + ClassGenerator.linkerAddGetterSetter(mi, className, memInfo); + } else if (memInfo.isInstanceGetter()) { + final MemberInfo setter = scriptClassInfo.findSetter(memInfo); + ClassGenerator.linkerAddGetterSetter(mi, className, memInfo, setter); + } + } + } + ClassGenerator.emitStaticInitSuffix(mi, className); + } + + /** + * External entry point for ScriptClassInfoCollector if run from the command line + * + * @param args arguments - one argument is needed, the name of the class to collect info from + * + * @throws IOException if there are problems reading class + */ + public static void main(final String[] args) throws IOException { + if (args.length != 1) { + System.err.println("Usage: " + ScriptClassInfoCollector.class.getName() + " <class>"); + System.exit(1); + } + + final String fileName = args[0].replace('.', '/') + ".class"; + final ScriptClassInfo sci = ClassGenerator.getScriptClassInfo(fileName); + if (sci == null) { + System.err.println("No @ScriptClass in " + fileName); + System.exit(2); + throw new AssertionError(); //guard against warning that sci is null below + } + + try { + sci.verify(); + } catch (final Exception e) { + System.err.println(e.getMessage()); + System.exit(3); + } + + final ClassWriter writer = ClassGenerator.makeClassWriter(); + try (final BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fileName))) { + final ClassReader reader = new ClassReader(bis); + final CheckClassAdapter checker = new CheckClassAdapter(writer); + final ScriptClassInstrumentor instr = new ScriptClassInstrumentor(checker, sci); + reader.accept(instr, 0); + } + + try (FileOutputStream fos = new FileOutputStream(fileName)) { + fos.write(writer.toByteArray()); + } + } +} diff --git a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java new file mode 100644 index 00000000..06032733 --- /dev/null +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.tools.nasgen; + +import java.lang.invoke.MethodHandle; +import java.lang.reflect.Method; +import jdk.internal.org.objectweb.asm.Type; +import jdk.nashorn.internal.objects.PrototypeObject; +import jdk.nashorn.internal.objects.ScriptFunctionImpl; +import jdk.nashorn.internal.runtime.PropertyMap; +import jdk.nashorn.internal.runtime.ScriptFunction; +import jdk.nashorn.internal.runtime.ScriptObject; +import jdk.nashorn.internal.runtime.linker.Lookup; + +/** + * String constants used for code generation/instrumentation. + */ +@SuppressWarnings("javadoc") +public interface StringConstants { + static final Type TYPE_METHOD = Type.getType(Method.class); + static final Type TYPE_METHODHANDLE = Type.getType(MethodHandle.class); + static final Type TYPE_METHODHANDLE_ARRAY = Type.getType(MethodHandle[].class); + static final Type TYPE_OBJECT = Type.getType(Object.class); + static final Type TYPE_CLASS = Type.getType(Class.class); + static final Type TYPE_STRING = Type.getType(String.class); + + // Nashorn types + static final Type TYPE_LOOKUP = Type.getType(Lookup.class); + 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 = "prototype"; + static final String PROTOTYPE_SUFFIX = "$Prototype"; + static final String CONSTRUCTOR_SUFFIX = "$Constructor"; + // This field name is known to Nashorn runtime (Context). + // Synchronize the name change, if needed at all. + static final String MAP_FIELD_NAME = "$nasgenmap$"; + static final String $CLINIT$ = "$clinit$"; + static final String CLINIT = "<clinit>"; + static final String INIT = "<init>"; + static final String DEFAULT_INIT_DESC = Type.getMethodDescriptor(Type.VOID_TYPE); + + static final String SCRIPTOBJECT_INIT_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_PROPERTYMAP); + + static final String METHODHANDLE_TYPE = TYPE_METHODHANDLE.getInternalName(); + + static final String OBJECT_TYPE = TYPE_OBJECT.getInternalName(); + static final String OBJECT_DESC = TYPE_OBJECT.getDescriptor(); + static final String OBJECT_ARRAY_DESC = Type.getDescriptor(Object[].class); + + static final String SCRIPTFUNCTION_TYPE = TYPE_SCRIPTFUNCTION.getInternalName(); + static final String SCRIPTFUNCTIONIMPL_TYPE = TYPE_SCRIPTFUNCTIONIMPL.getInternalName(); + static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION = "makeFunction"; + static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC = + Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE); + static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC = + Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE, TYPE_METHODHANDLE_ARRAY); + + static final String SCRIPTFUNCTIONIMPL_INIT_DESC3 = + Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_METHODHANDLE_ARRAY); + static final String SCRIPTFUNCTIONIMPL_INIT_DESC4 = + Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_PROPERTYMAP, TYPE_METHODHANDLE_ARRAY); + static final String SCRIPTFUNCTION_SETARITY = "setArity"; + static final String SCRIPTFUNCTION_SETARITY_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE); + static final String PROTOTYPEOBJECT_TYPE = TYPE_PROTOTYPEOBJECT.getInternalName(); + static final String PROTOTYPEOBJECT_SETCONSTRUCTOR = "setConstructor"; + static final String PROTOTYPEOBJECT_SETCONSTRUCTOR_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_OBJECT, TYPE_OBJECT); + static final String SCRIPTOBJECT_TYPE = TYPE_SCRIPTOBJECT.getInternalName(); + static final String MAP_TYPE = TYPE_PROPERTYMAP.getInternalName(); + static final String MAP_DESC = TYPE_PROPERTYMAP.getDescriptor(); + static final String MAP_NEWMAP = "newMap"; + static final String MAP_NEWMAP_DESC = Type.getMethodDescriptor(TYPE_PROPERTYMAP, TYPE_CLASS); + static final String MAP_DUPLICATE = "duplicate"; + static final String MAP_DUPLICATE_DESC = Type.getMethodDescriptor(TYPE_PROPERTYMAP); + static final String MAP_SETFLAGS = "setFlags"; + static final String LOOKUP_TYPE = TYPE_LOOKUP.getInternalName(); + static final String LOOKUP_GETMETHOD = "getMethod"; + static final String LOOKUP_NEWPROPERTY = "newProperty"; + static final String LOOKUP_NEWPROPERTY_DESC = + Type.getMethodDescriptor(TYPE_PROPERTYMAP, TYPE_PROPERTYMAP, TYPE_STRING, Type.INT_TYPE, TYPE_METHODHANDLE, TYPE_METHODHANDLE); + static final String GETTER_PREFIX = "G$"; + static final String SETTER_PREFIX = "S$"; + + // ScriptObject.getClassName() method. + static final String GET_CLASS_NAME = "getClassName"; + static final String GET_CLASS_NAME_DESC = Type.getMethodDescriptor(TYPE_STRING); +} diff --git a/docs/DEVELOPER_README b/docs/DEVELOPER_README new file mode 100644 index 00000000..747379bc --- /dev/null +++ b/docs/DEVELOPER_README @@ -0,0 +1,445 @@ +This document describes system properties that are used for internal +debugging and instrumentation purposes, along with the system loggers, +which are used for the same thing. + +This document is intended as a developer resource, and it is not +needed as Nashorn documentation for normal usage. Flags and system +properties described herein are subject to change without notice. + +===================================== +1. System properties used internally +===================================== + +This documentation of the system property flags assume that the +default value of the flag is false, unless otherwise specified. + + +SYSTEM PROPERTY: -Dnashorn.callsiteaccess.debug + +See the description of the access logger below. This flag is +equivalent to enabling the access logger with "info" level. + + +SYSTEM PROPERTY: -Dnashorn.compiler.ints.disable + +This flag prevents ints and longs (non double values) from being used +for any primitive representation in the lowered IR. This is default +false, i.e Lower will attempt to use integer variables as long as it +can. For example, var x = 17 would try to use x as an integer, unless +other operations occur later that require coercion to wider type, for +example x *= 17.1; + + +SYSTEM PROPERTY: -Dnashorn.compiler.intarithmetic + +Arithmetic operations in Nashorn (except bitwise ones) typically +coerce the operands to doubles (as per the JavaScript spec). To switch +this off and remain in integer mode, for example for "var x = a&b; var +y = c&d; var z = x*y;", use this flag. This will force the +multiplication of variables that are ints to be done with the IMUL +bytecode and the result "z" to become an int. + +WARNING: Note that is is experimental only to ensure that type support +exists for all primitive types. The generated code is unsound. This +will be the case until we do optimizations based on it. There is a CR +in Nashorn to do better range analysis, and ensure that this is only +done where the operation can't overflow into a wider type. Currently +no overflow checking is done, so at the moment, until range analysis +has been completed, this option is turned off. + +We've experimented by using int arithmetic for everything and putting +overflow checks afterwards, which would recompute the operation with +the correct precision, but have yet to find a configuration where this +is faster than just using doubles directly, even if the int operation +does not overflow. Getting access to a JVM intrinsic that does branch +on overflow would probably alleviate this. + +There is also a problem with this optimistic approach if the symbol +happens to reside in a local variable slot in the bytecode, as those +are strongly typed. Then we would need to split large sections of +control flow, so this is probably not the right way to go, while range +analysis is. There is a large difference between integer bytecode +without overflow checks and double bytecode. The former is +significantly faster. + + +SYSTEM PROPERTY: -Dnashorn.codegen.debug, -Dnashorn.codegen.debug.trace=<x> + +See the description of the codegen logger below. + + +SYSTEM_PROPERTY: -Dnashorn.fields.debug + +See the description on the fields logger below. + + +SYSTEM PROPERTY: -Dnashorn.fields.dual + +When this property is true, Nashorn will attempt to use primitive +fields for AccessorProperties (currently just AccessorProperties, not +spill properties). Memory footprint for script objects will increase, +as we need to maintain both a primitive field (a long) as well as an +Object field for the property value. 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. + +While dual fields in theory runs significantly faster than Object +fields due to reduction of boxing and memory allocation overhead, +there is still work to be done to make this a general purpose +solution. Research is ongoing. + +In the future, this might complement or be replaced by experimental +feature sun.misc.TaggedArray, which has been discussed on the mlvm +mailing list. TaggedArrays are basically a way to share data space +between primitives and references, and have the GC understand this. + +As long as only primitive values are written to the fields and enough +type information exists to make sure that any reads don't have to be +uselessly boxed and unboxed, this is significantly faster than the +standard "Objects only" approach that currently is the default. See +test/examples/dual-fields-micro.js for an example that runs twice as +fast with dual fields as without them. Here, the compiler, can +determine that we are dealing with numbers only throughout the entire +property life span of the properties involved. + +If a "real" object (not a boxed primitive) is written to a field that +has a primitive representation, its callsite is relinked and an Object +field is used forevermore for that particular field in that +PropertyMap and its children, even if primitives are later assigned to +it. + +As the amount of compile time type information is very small in a +dynamic language like JavaScript, it is frequently the case that +something has to be treated as an object, because we don't know any +better. In reality though, it is often a boxed primitive is stored to +an AccessorProperty. The fastest way to handle this soundly is to use +a callsite typecheck and avoid blowing the field up to an Object. We +never revert object fields to primitives. Ping-pong:ing back and forth +between primitive representation and Object representation would cause +fatal performance overhead, so this is not an option. + +For a general application the dual fields approach is still slower +than objects only fields in some places, about the same in most cases, +and significantly faster in very few. This is due the program using +primitives, but we still can't prove it. For example "local_var a = +call(); field = a;" may very well write a double to the field, but the +compiler dare not guess a double type if field is a local variable, +due to bytecode variables being strongly typed and later non +interchangeable. To get around this, the entire method would have to +be replaced and a continuation retained to restart from. We believe +that the next steps we should go through are instead: + +1) Implement method specialization based on callsite, as it's quite +frequently the case that numbers are passed around, but currently our +function nodes just have object types visible to the compiler. For +example "var b = 17; func(a,b,17)" is an example where two parameters +can be specialized, but the main version of func might also be called +from another callsite with func(x,y,"string"). + +2) This requires lazy jitting as the functions have to be specialized +per callsite. + +Even though "function square(x) { return x*x }" might look like a +trivial function that can always only take doubles, this is not +true. Someone might have overridden the valueOf for x so that the +toNumber coercion has side effects. To fulfil JavaScript semantics, +the coercion has to run twice for both terms of the multiplication +even if they are the same object. This means that call site +specialization is necessary, not parameter specialization on the form +"function square(x) { var xd = (double)x; return xd*xd; }", as one +might first think. + +Generating a method specialization for any variant of a function that +we can determine by types at compile time is a combinatorial explosion +of byte code (try it e.g. on all the variants of am3 in the Octane +benchmark crypto.js). Thus, this needs to be lazy + +3) Possibly optimistic callsite writes, something on the form + +x = y; //x is a field known to be a primitive. y is only an object as +far as we can tell + +turns into + +try { + x = (int)y; +} catch (X is not an integer field right now | ClassCastException e) { + x = y; +} + +Mini POC shows that this is the key to a lot of dual field performance +in seemingly trivial micros where one unknown object, in reality +actually a primitive, foils it for us. Very common pattern. Once we +are "all primitives", dual fields runs a lot faster than Object fields +only. + +We still have to deal with objects vs primitives for local bytecode +slots, possibly through code copying and versioning. + + +SYSTEM PROPERTY: -Dnashorn.compiler.symbol.trace=<x> + +When this property is set, creation and manipulation of any symbol +named "x" will show information about when the compiler changes its +type assumption, bytecode local variable slot assignment and other +data. This is useful if, for example, a symbol shows up as an Object, +when you believe it should be a primitive. Usually there is an +explanation for this, for example that it exists in the global scope +and type analysis has to be more conservative. In that case, the stack +trace upon type change to object will usually tell us why. + + +SYSTEM PROPERTY: nashorn.lexer.xmlliterals + +If this property it set, it means that the Lexer should attempt to +parse XML literals, which would otherwise generate syntax +errors. Warning: there are currently no unit tests for this +functionality. + +XML literals, when this is enabled, end up as standard LiteralNodes in +the IR. + + +SYSTEM_PROPERTY: nashorn.debug + +If this property is set to true, Nashorn runs in Debug mode. Debug +mode is slightly slower, as for example statistics counters are enabled +during the run. Debug mode makes available a NativeDebug instance +called "Debug" in the global space that can be used to print property +maps and layout for script objects, as well as a "dumpCounters" method +that will print the current values of the previously mentioned stats +counters. + +These functions currently exists for Debug: + +"map" - print(Debug.map(x)) will dump the PropertyMap for object x to +stdout (currently there also exist functions called "embedX", where X +is a value from 0 to 3, that will dump the contents of the embed pool +for the first spill properties in any script object and "spill", that +will dump the contents of the growing spill pool of spill properties +in any script object. This is of course subject to change without +notice, should we change the script object layout. + +"methodHandle" - this method returns the method handle that is used +for invoking a particular script function. + +"identical" - this method compares two script objects for reference +equality. It is a == Java comparison + +"dumpCounters" - will dump the debug counters' current values to +stdout. + +Currently we count number of ScriptObjects in the system, number of +Scope objects in the system, number of ScriptObject listeners added, +removed and dead (without references). + +We also count number of ScriptFunctions, ScriptFunction invocations +and ScriptFunction allocations. + +Furthermore we count PropertyMap statistics: how many property maps +exist, how many times were property maps cloned, how many times did +the property map history cache hit, prevent new allocations, how many +prototype invalidations were done, how many time the property map +proto cache hit. + +Finally we count callsite misses on a per callsite bases, which occur +when a callsite has to be relinked, due to a previous assumption of +object layout being invalidated. + + +SYSTEM PROPERTY: nashorn.methodhandles.debug, +nashorn.methodhandles.debug=create + +If this property is enabled, each MethodHandle related call that uses +the java.lang.invoke package gets its MethodHandle intercepted and an +instrumentation printout of arguments and return value appended to +it. This shows exactly which method handles are executed and from +where. (Also MethodTypes and SwitchPoints). This can be augmented with +more information, for example, instance count, by subclassing or +further extending the TraceMethodHandleFactory implementation in +MethodHandleFactory.java. + +If the property is specialized with "=create" as its option, +instrumentation will be shown for method handles upon creation time +rather than at runtime usage. + + +SYSTEM PROPERTY: nashorn.methodhandles.debug.stacktrace + +This does the same as nashorn.methodhandles.debug, but when enabled +also dumps the stack trace for every instrumented method handle +operation. Warning: This is enormously verbose, but provides a pretty +decent "grep:able" picture of where the calls are coming from. + +See the description of the codegen logger below for a more verbose +description of this option + + +SYSTEM PROPERTY: nashorn.scriptfunction.specialization.disable + +There are several "fast path" implementations of constructors and +functions in the NativeObject classes that, in their original form, +take a variable amount of arguments. Said functions are also declared +to take Object parameters in their original form, as this is what the +JavaScript specification mandates. + +However, we often know quite a lot more at a callsite of one of these +functions. For example, Math.min is called with a fixed number (2) of +integer arguments. The overhead of boxing these ints to Objects and +folding them into an Object array for the generic varargs Math.min +function is an order of magnitude slower than calling a specialized +implementation of Math.min that takes two integers. Specialized +functions and constructors are identified by the tag +@SpecializedFunction and @SpecializedConstructor in the Nashorn +code. The linker will link in the most appropriate (narrowest types, +right number of types and least number of arguments) specialization if +specializations are available. + +Every ScriptFunction may carry specializations that the linker can +choose from. This framework will likely be extended for user defined +functions. The compiler can often infer enough parameter type info +from callsites for in order to generate simpler versions with less +generic Object types. This feature depends on future lazy jitting, as +there tend to be many calls to user defined functions, some where the +callsite can be specialized, some where we mostly see object +parameters even at the callsite. + +If this system property is set to true, the linker will not attempt to +use any specialized function or constructor for native objects, but +just call the generic one. + + +SYSTEM PROPERTY: nashorn.tcs.miss.samplePercent=<x> + +When running with the trace callsite option (-tcs), Nashorn will count +and instrument any callsite misses that require relinking. As the +number of relinks is large and usually produces a lot of output, this +system property can be used to constrain the percentage of misses that +should be logged. Typically this is set to 1 or 5 (percent). 1% is the +default value. + + +SYSTEM_PROPERTY: nashorn.profilefile=<filename> + +When running with the profile callsite options (-pcs), Nashorn will +dump profiling data for all callsites to stderr as a shutdown hook. To +instead redirect this to a file, specify the path to the file using +this system property. + + +=============== +2. The loggers. +=============== + +The Nashorn loggers can be used to print per-module or per-subsystem +debug information with different levels of verbosity. The loggers for +a given subsystem are available are enabled by using + +--log=<systemname>[:<level>] + +on the command line. + +Here <systemname> identifies the name of the subsystem to be logged +and the optional colon and level argument is a standard +java.util.logging.Level name (severe, warning, info, config, fine, +finer, finest). If the level is left out for a particular subsystem, +it defaults to "info". Any log message logged as the level or a level +that is more important will be output to stderr by the logger. + +Several loggers can be enabled by a single command line option, by +putting a comma after each subsystem/level tuple (or each subsystem if +level is unspecified). The --log option can also be given multiple +times on the same command line, with the same effect. + +For example: --log=codegen,fields:finest is equivalent to +--log=codegen:info --log=fields:finest + +The subsystems that currently support logging are: + + +* compiler + +The compiler is in charge of turning source code and function nodes +into byte code, and installs the classes into a class loader +controlled from the Context. Log messages are, for example, about +things like new compile units being allocated. The compiler has global +settings that all the tiers of codegen (e.g. Lower and CodeGenerator) +use. + + +* codegen + +The code generator is the emitter stage of the code pipeline, and +turns the lowest tier of a FunctionNode into bytecode. Codegen logging +shows byte codes as they are being emitted, line number information +and jumps. It also shows the contents of the bytecode stack prior to +each instruction being emitted. This is a good debugging aid. For +example: + +[codegen] #41 line:2 (f)_afc824e +[codegen] #42 load symbol x slot=2 +[codegen] #43 {1:O} load int 0 +[codegen] #44 {2:I O} dynamic_runtime_call GT:ZOI_I args=2 returnType=boolean +[codegen] #45 signature (Ljava/lang/Object;I)Z +[codegen] #46 {1:Z} ifeq ternary_false_5402fe28 +[codegen] #47 load symbol x slot=2 +[codegen] #48 {1:O} goto ternary_exit_107c1f2f +[codegen] #49 ternary_false_5402fe28 +[codegen] #50 load symbol x slot=2 +[codegen] #51 {1:O} convert object -> double +[codegen] #52 {1:D} neg +[codegen] #53 {1:D} convert double -> object +[codegen] #54 {1:O} ternary_exit_107c1f2f +[codegen] #55 {1:O} return object + +shows a ternary node being generated for the sequence "return x > 0 ? +x : -x" + +The first number on the log line is a unique monotonically increasing +emission id per bytecode. There is no guarantee this is the same id +between runs. depending on non deterministic code +execution/compilation, but for small applications it usually is. If +the system variable -Dnashorn.codegen.debug.trace=<x> is set, where x +is a bytecode emission id, a stack trace will be shown as the +particular bytecode is about to be emitted. This can be a quick way to +determine where it comes from without attaching the debugger. "Who +generated that neg?" + +The --log=codegen option is equivalent to setting the system variable +"nashorn.codegen.debug" to true. + + +* lower + +The lowering annotates a FunctionNode with symbols for each identifier +and transforms high level constructs into lower level ones, that the +CodeGenerator consumes. + +Lower logging typically outputs things like post pass actions, +insertions of casts because symbol types have been changed and type +specialization information. Currently very little info is generated by +this logger. This will probably change. + + +* access + +The --log=access option is equivalent to setting the system variable +"nashorn.callsiteaccess.debug" to true. There are several levels of +the access logger, usually the default level "info" is enough + +It is very simple to create your own logger. Use the DebugLogger class +and give the subsystem name as a constructor argument. + + +* fields + +The --log=fields option (at info level) is equivalent to setting the +system variable "nashorn.fields.debug" to true. At the info level it +will only show info about type assumptions that were invalidated. If +the level is set to finest, it will also trace every AccessorProperty +getter and setter in the program, show arguments, return values +etc. It will also show the internal representation of respective field +(Object in the normal case, unless running with the dual field +representation)
\ No newline at end of file diff --git a/docs/genshelldoc.js b/docs/genshelldoc.js new file mode 100644 index 00000000..c3cf5c30 --- /dev/null +++ b/docs/genshelldoc.js @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Generate HTML documentation for shell tool. Re-run this tool to regenerate + * html doc when you change options. + * + * Usage: + * + * jjs -scripting genshelldoc.js > shell.html + */ + +var Options = Packages.jdk.nashorn.internal.runtime.options.Options; +var title = "Nashorn command line shell tool"; + +print(<<PREFIX +<html> +<head> +<title> +${title} +</title> +</head> +<body> +<h1>Usage</h1> +<p> +<code> +<b>jjs <options> <script-files> [ -- <script-arguments> ]</b> +</code> +</p> + +<h1>${title} options</h1> + +<table border="0"> +<tr> +<th>name</th> +<th>type</th> +<th>default</th> +<th>description</th> +</tr> +PREFIX); + +for each (opt in Options.validOptions) { + +var isTimezone = (opt.type == "timezone"); +var defValue = opt.defaultValue; +if (defValue == null) { + defValue = "<none>"; +} + +if (isTimezone) { + // don't output current user's timezone + defValue = "<default-timezone>" +} + +print(<<ROW + <tr> + <td><b>${opt.name} ${opt.shortName == null? "" : opt.shortName}</b></td> + <td>${opt.type}</td> + <td>${defValue}</td> + <td>${opt.description}</td> + </tr> +ROW); + +} + +print(<<SUFFIX +</table> +</body> +</html> +SUFFIX); diff --git a/make/Makefile b/make/Makefile new file mode 100644 index 00000000..7d768708 --- /dev/null +++ b/make/Makefile @@ -0,0 +1,224 @@ +# +# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +# Makefile for nashorn: wrapper around Ant build.xml file + +# +# On Solaris, the standard 'make' utility will not work with these makefiles. +# This little rule is only understood by Solaris make, and is harmless +# when seen by the GNU make tool. If using Solaris make, this causes the +# make command to fail. +# +SUN_MAKE_TEST:sh = @echo "ERROR: PLEASE USE GNU VERSION OF MAKE"; exit 33 + +# +# Minimal platform defs +# Need FullPath because we can't rely on gnumake abspath, until we use v3.81 +# + +SYSTEM_UNAME := $(shell uname) + +# Where is unwanted output to be delivered? +# On Windows, MKS uses the special file "NUL", cygwin uses the customary unix file. +ifeq ($(SYSTEM_UNAME), Windows_NT) +DEV_NULL = NUL +else +DEV_NULL = /dev/null +endif + +ifneq (,$(findstring CYGWIN,$(SYSTEM_UNAME))) +USING_CYGWIN = true +endif + +ifdef USING_CYGWIN +define FullPath +$(shell cygpath -a -s -m $1 2> $(DEV_NULL)) +endef +else +define FullPath +$(shell cd $1 2> $(DEV_NULL) && pwd) +endef +endif + +# +# Makefile args +# + +ifdef QUIET + ANT_OPTIONS += -quiet +endif + +ifdef VERBOSE + ANT_OPTIONS += -verbose -debug +endif + +ifdef JDK_VERSION + ANT_OPTIONS += -Djdk.version=$(JDK_VERSION) +endif + +ifdef FULL_VERSION + ANT_OPTIONS += -Dfull.version='$(FULL_VERSION)' # will contain spaces +endif + +ifdef MILESTONE +ifneq ($(MILESTONE),fcs) + ANT_OPTIONS += -Dmilestone=$(MILESTONE) +else + ANT_OPTIONS += -Drelease=$(JDK_VERSION) +endif +endif + +ifdef BUILD_NUMBER + ANT_OPTIONS += -Dbuild.number=$(BUILD_NUMBER) +else + ifdef JDK_BUILD_NUMBER + ANT_OPTIONS += -Dbuild.number=$(JDK_BUILD_NUMBER) + endif +endif + +ifeq ($(VARIANT), DBG) + ANT_OPTIONS += -Djavac.debug=true +else + ifeq ($(VARIANT), OPT) + ANT_OPTIONS += -Djavac.debug=false + endif +endif + +ifeq ($(DEBUG_CLASSFILES), true) + ANT_OPTIONS += -Djavac.debug=true + ANT_OPTIONS += -Ddebug.classfiles=true +endif + +# Note: jdk/make/common/Defs.gmk uses LANGUAGE_VERSION (-source NN) +# and the somewhat misnamed CLASS_VERSION (-target NN) +ifdef TARGET_CLASS_VERSION + ANT_OPTIONS += -Djavac.target=$(TARGET_CLASS_VERSION) +else + ifdef JAVAC_TARGET_ARG + ANT_OPTIONS += -Djavac.target=$(JAVAC_TARGET_ARG) + endif +endif + +ifdef SOURCE_LANGUAGE_VERSION + ANT_OPTIONS += -Djavac.source=$(SOURCE_LANGUAGE_VERSION) +else + ifdef JAVAC_SOURCE_ARG + ANT_OPTIONS += -Djavac.source=$(JAVAC_SOURCE_ARG) + endif +endif + +ifdef ALT_BOOTDIR + ANT_OPTIONS += -Dboot.java.home=$(ALT_BOOTDIR) + ANT_JAVA_HOME = JAVA_HOME=$(ALT_BOOTDIR) +endif + +# To facilitate bootstrapping, much of langtools can be compiled with (just) +# a boot JDK. However, some source files need to be compiled against +# new JDK API. In a bootstrap build, an import JDK may not be available, +# so build.xml can also build against the source files in a jdk repo, +# in which case it will automatically generate stub files for the new JDK API. +ifdef JDK_TOPDIR + ANT_OPTIONS += -Dimport.jdk=$(JDK_TOPDIR) +else + ifdef ALT_JDK_TOPDIR + ANT_OPTIONS += -Dimport.jdk=$(ALT_JDK_TOPDIR) + else + ifdef ALT_JDK_IMPORT_PATH + ANT_OPTIONS += -Dimport.jdk=$(ALT_JDK_IMPORT_PATH) + endif + endif +endif + +ifdef ALT_OUTPUTDIR + OUTPUTDIR = $(ALT_OUTPUTDIR) + ANT_OPTIONS += -Dbuild.dir=$(ALT_OUTPUTDIR)/build + ANT_OPTIONS += -Ddist.dir=$(ALT_OUTPUTDIR)/dist +else + OUTPUTDIR = .. +endif +#ABS_OUTPUTDIR = $(abspath $(OUTPUTDIR)) +ABS_OUTPUTDIR = $(call FullPath,$(OUTPUTDIR)) + +ANT_TMPDIR = $(ABS_OUTPUTDIR)/build/ant-tmp +ANT_OPTS = ANT_OPTS=-Djava.io.tmpdir='$(ANT_TMPDIR)' + +ifdef FINDBUGS_HOME + ANT_OPTIONS += -Dfindbugs.home=$(FINDBUGS_HOME) +endif + +ifdef ANT_HOME + ANT = $(ANT_HOME)/bin/ant + ifneq ($(shell test -x $(ANT) && echo OK), OK) + $(error $(ANT) not found -- please update ANT_HOME) + endif +else + ANT = ant + ifneq ($(shell test -x "`which $(ANT)`" && echo OK), OK) + $(error 'ant' not found -- please set ANT_HOME or put 'ant' on your PATH) + endif +endif + +# Default target and expected 'do everything' target +# comments docs to avoid too many ASM warnings +# all: test docs + +all: test + +# Standard make clobber target +clobber: clean + +# All ant targets of interest +ANT_TARGETS = clean jar javadoc shelldoc docs test test262 test262parallel # for now + +# Create diagnostics log (careful, ant 1.8.0 -diagnostics always does an exit 1) +$(OUTPUTDIR)/build/ant-diagnostics.log: + @mkdir -p $(OUTPUTDIR)/build $(ANT_TMPDIR) + @$(RM) $@ + $(ANT_JAVA_HOME) $(ANT_OPTS) $(ANT) -diagnostics > $@ ; \ + $(ANT_JAVA_HOME) $(ANT_OPTS) $(ANT) -version >> $@ + +# Create a make target for each +$(ANT_TARGETS): $(OUTPUTDIR)/build/ant-diagnostics.log + @ mkdir -p $(OUTPUTDIR)/build $(ANT_TMPDIR) + $(ANT_JAVA_HOME) $(ANT_OPTS) $(ANT) $(ANT_OPTIONS) $@ + +#------------------------------------------------------------------- +# +# Targets for Oracle's internal JPRT build system + +CD = cd +ZIP = zip + +JPRT_ARCHIVE_BUNDLE=$(ABS_OUTPUTDIR)/$(JPRT_BUILD_FLAVOR)-bundle.zip + +jprt_build_product jprt_build_debug jprt_build_fastdebug: all + ( $(CD) $(OUTPUTDIR) && \ + $(ZIP) -q -r $(JPRT_ARCHIVE_BUNDLE) build dist ) + +#------------------------------------------------------------------- + +# Declare these phony (not filenames) +.PHONY: $(ANT_TARGETS) all clobber \ + jprt_build_product jprt_build_debug jprt_build_fastdebug diff --git a/make/build-benchmark.xml b/make/build-benchmark.xml new file mode 100644 index 00000000..b6dce195 --- /dev/null +++ b/make/build-benchmark.xml @@ -0,0 +1,348 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + or visit www.oracle.com if you need additional information or have any + questions. +--> +<project name="nashorn-benchmarks" default="all" basedir=".."> + + <target name="octane-init" depends="jar"> + <fileset id="octane-set" + dir="${octane-test-sys-prop.test.js.roots}" + excludes="${octane-test-sys-prop.test.js.exclude.list}"> + <include name="**/*.js"/> + </fileset> + <pathconvert pathsep=" " property="octane-tests" refid="octane-set"/> + <property name="extra-arg" value=""/> + </target> + + <!-- box2d --> + <target name="box2d-init"> + <property name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/box2d.js"/> + </target> + + <target name="octane-box2d" depends="jar, box2d-init, octane-verbose"> + <antcall target="run-octane"/> + </target> + + <target name="octane-box2d-v8" depends="jar, box2d-init, octane-verbose"> + <antcall target="run-octane-v8"/> + </target> + + <target name="octane-box2d-rhino" depends="jar, box2d-init, octane-verbose"> + <antcall target="run-octane-rhino"/> + </target> + + <!-- code-load --> + <target name="code-load-init"> + <property name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/code-load.js"/> + </target> + + <target name="octane-code-load" depends="jar, code-load-init, octane-verbose"> + <antcall target="run-octane"/> + </target> + + <target name="octane-code-load-v8" depends="jar, code-load-init, octane-verbose"> + <antcall target="run-octane-v8"/> + </target> + + <target name="octane-code-load-rhino" depends="jar, code-load-init, octane-verbose"> + <antcall target="run-octane-rhino"/> + </target> + + <!-- crypto --> + <target name="crypto-init"> + <property name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/crypto.js"/> + </target> + + <target name="octane-crypto" depends="jar, crypto-init, octane-verbose"> + <antcall target="run-octane"/> + </target> + + <target name="octane-crypto-v8" depends="jar, crypto-init, octane-verbose"> + <antcall target="run-octane-v8"/> + </target> + + <target name="octane-crypto-rhino" depends="jar, crypto-init, octane-verbose"> + <antcall target="run-octane-rhino"/> + </target> + + <!-- deltablue --> + <target name="deltablue-init"> + <property name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/deltablue.js"/> + </target> + + <target name="octane-deltablue" depends="jar, deltablue-init, octane-verbose"> + <antcall target="run-octane"/> + </target> + + <target name="octane-deltablue-v8" depends="jar, deltablue-init, octane-verbose"> + <antcall target="run-octane-v8"/> + </target> + + <target name="octane-deltablue-rhino" depends="jar, deltablue-init, octane-verbose"> + <antcall target="run-octane-rhino"/> + </target> + + <!-- earley-boyer --> + <target name="earley-boyer-init"> + <property name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/earley-boyer.js"/> + </target> + + <target name="octane-earley-boyer" depends="jar, earley-boyer-init, octane-verbose"> + <antcall target="run-octane"/> + </target> + + <target name="octane-earley-boyer-v8" depends="jar, earley-boyer-init, octane-verbose"> + <antcall target="run-octane-v8"/> + </target> + + <target name="octane-earley-boyer-rhino" depends="jar, earley-boyer-init, octane-verbose"> + <antcall target="run-octane-rhino"/> + </target> + + <!-- gbemu --> + <target name="gbemu-init"> + <property name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/gbemu.js"/> + </target> + + <target name="octane-gbemu" depends="jar, gbemu-init, octane-verbose"> + <antcall target="run-octane"/> + </target> + + <target name="octane-gbemu-v8" depends="jar, gbemu-init, octane-verbose"> + <antcall target="run-octane-v8"/> + </target> + + <target name="octane-gbemu-rhino" depends="jar, gbemu-init, octane-verbose"> + <antcall target="run-octane-rhino"/> + </target> + + <!-- navier-stokes --> + <target name="navier-stokes-init"> + <property name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/navier-stokes.js"/> + </target> + + <target name="octane-navier-stokes" depends="jar, navier-stokes-init, octane-verbose"> + <antcall target="run-octane"/> + </target> + + <target name="octane-navier-stokes-v8" depends="jar, navier-stokes-init, octane-verbose"> + <antcall target="run-octane-v8"/> + </target> + + <target name="octane-navier-stokes-rhino" depends="jar, navier-stokes-init, octane-verbose"> + <antcall target="run-octane-rhino"/> + </target> + + <!-- pdfjs --> + <target name="pdfjs-init"> + <property name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/pdfjs.js"/> + </target> + + <target name="octane-pdfjs" depends="jar, pdfjs-init, octane-verbose"> + <antcall target="run-octane"/> + </target> + + <target name="octane-pdfjs-v8" depends="jar, pdfjs-init, octane-verbose"> + <antcall target="run-octane-v8"/> + </target> + + <target name="octane-pdfjs-rhino" depends="jar, pdfjs-init, octane-verbose"> + <antcall target="run-octane-rhino"/> + </target> + + <!-- raytrace --> + <target name="raytrace-init"> + <property name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/raytrace.js"/> + </target> + + <target name="octane-raytrace" depends="jar, raytrace-init, octane-verbose"> + <antcall target="run-octane"/> + </target> + + <target name="octane-raytrace-v8" depends="jar, raytrace-init, octane-verbose"> + <antcall target="run-octane-v8"/> + </target> + + <target name="octane-raytrace-rhino" depends="jar, raytrace-init, octane-verbose"> + <antcall target="run-octane-rhino"/> + </target> + + <!-- regexp --> + <target name="regexp-init"> + <property name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/regexp.js"/> + </target> + + <target name="octane-regexp" depends="jar, regexp-init, octane-verbose"> + <antcall target="run-octane"/> + </target> + + <target name="octane-regexp-octane-v8" depends="jar, regexp-init, octane-verbose"> + <antcall target="run-octane-v8"/> + </target> + + <target name="octane-regexp-rhino" depends="jar, regexp-init, octane-verbose"> + <antcall target="run-octane-rhino"/> + </target> + + + <!-- splay --> + <target name="splay-init"> + <property name="octane-tests" value="${octane-test-sys-prop.test.js.roots}/splay.js"/> + </target> + + <target name="octane-splay" depends="jar, splay-init, octane-verbose"> + <antcall target="run-octane"/> + </target> + + <target name="octane-splay-v8" depends="jar, splay-init, octane-verbose"> + <antcall target="run-octane-v8"/> + </target> + + <target name="octane-splay-rhino" depends="jar, splay-init, octane-verbose"> + <antcall target="run-octane-rhino"/> + </target> + + <target name="octane-verbose"> + <property name="extra-arg" value="--verbose"/> + </target> + + <!-- run octane benchmarks using Nashorn as runtime --> + <target name="octane" depends="octane-init"> + <antcall target="run-octane"/> + </target> + + <!-- run octane benchmarks using octane as runtime --> + <target name="octane-v8" depends="octane-init"> + <antcall target="run-octane-v8"/> + </target> + + <!-- run octane benchmarks using Rhino as runtime --> + <target name="octane-rhino" depends="octane-init"> + <antcall target="run-octane-rhino"/> + </target> + + <target name="run-octane"> + <java classname="${nashorn.shell.tool}" + classpath="${run.test.classpath}" + fork="true" + dir="."> + <jvmarg line="${boot.class.path}"/> + <jvmarg line="${ext.class.path}"/> + <jvmarg line="${run.test.jvmargs.octane}"/> + <arg value="${octane-test-sys-prop.test.js.framework}"/> + <arg value="--"/> + <arg value="${octane-tests}"/> + <arg value="--runtime"/> + <arg value="Nashorn"/> + <arg value="--verbose"/> + <arg value="--iterations 8"/> + <arg value="${extra-arg}"/> + </java> + </target> + + <target name="run-octane-v8"> + <exec executable="${v8.shell}"> + <arg value="${octane-test-sys-prop.test.js.framework}"/> + <arg value="--"/> + <arg value="${octane-tests}"/> + <arg value="--runtime"/> + <arg value="v8"/> + <arg value="--verbose"/> + <arg value="--iterations 8"/> + <arg value="${extra-arg}"/> + </exec> + </target> + + <target name="run-octane-rhino"> + <java jar="${rhino.jar}" + classpath="${run.test.classpath}" + fork="true" + dir="."> + <jvmarg line="${boot.class.path}"/> + <jvmarg line="${run.test.jvmargs.octane}"/> + <arg value="${octane-test-sys-prop.test.js.framework}"/> + <arg value="${octane-tests}"/> + <arg value="--runtime"/> + <arg value="Rhino"/> + <arg value="--verbose"/> + <arg value="--iterations 8"/> + <arg value="${extra-arg}"/> + </java> + </target> + + <!-- run octane with all known runtimes for comparison --> + <target name="octane-all" depends="octane, octane-v8, octane-rhino"> + <exec executable="${v8.shell}"> + <arg value="${octane-test-sys-prop.test.js.framework}"/> + <arg value="${octane-tests}/"/> + </exec> + </target> + + <target name="sunspider-init" depends="jar"> + <fileset id="sunspider-set" + dir="${sunspider-test-sys-prop.test.js.roots}" + excludes="${sunspider-test-sys-prop.test.js.exclude.list}"> + <include name="**/*.js"/> + </fileset> + <pathconvert pathsep=" " property="sunspider-tests" refid="sunspider-set"/> + </target> + + <!-- run sunspider with Nashorn --> + <target name="sunspider" depends="sunspider-init"> + <java classname="${nashorn.shell.tool}" + classpath="${run.test.classpath}" + fork="true" + dir="."> + <jvmarg line="${boot.class.path}"/> + <jvmarg line="${ext.class.path}"/> + <jvmarg line="${run.test.jvmargs}"/> + <arg value="-timezone=PST"/> + <arg value="--class-cache-size=50"/> + <arg value="${sunspider-test-sys-prop.test.js.framework}"/> + <arg value="--"/> + <arg value="${sunspider-tests}/"/> + </java> + </target> + + <!-- run sunspider with v8 --> + <target name="sunspider-v8" depends="sunspider-init"> + <exec executable="${v8.shell}"> + <arg value="${sunspider-test-sys-prop.test.js.framework}"/> + <arg value="--"/> + <arg value="${sunspider-tests}/"/> + </exec> + </target> + + <!-- run sunspider with Rhino --> + <target name="sunspider-rhino" depends="sunspider-init"> + <java jar="${rhino.jar}" + classpath="${run.test.classpath}" + fork="true" + dir="."> + <jvmarg line="${boot.class.path}"/> + <jvmarg line="${run.test.jvmargs}"/> + <arg value="${sunspider-test-sys-prop.test.js.framework}"/> + <arg value="${sunspider-tests}/"/> + </java> + </target> + +</project> diff --git a/make/build-nasgen.xml b/make/build-nasgen.xml new file mode 100644 index 00000000..fe5a6782 --- /dev/null +++ b/make/build-nasgen.xml @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + or visit www.oracle.com if you need additional information or have any + questions. +--> +<project name="build-nasgen" default="run-nasgen" basedir=".."> + <description>Builds and runs nasgen.</description> + <import file="build.xml"/> + + <target name="build-nasgen" depends="compile-asm"> + <ant inheritAll="false" dir="${basedir}/buildtools/nasgen" + antfile="build.xml" target="jar"/> + </target> + + <target name="run-nasgen" depends="build-nasgen"> + <java classname="${nasgen.tool}" fork="true" failonerror="true"> + <classpath> + <pathelement location="${basedir}/jcov2/lib/jcov_j2se_rt.jar"/> + <pathelement location="${basedir}/buildtools/nasgen/dist/nasgen.jar"/> + <pathelement path="${basedir}/build/classes"/> + </classpath> + <arg value="${basedir}/build/classes"/> + <arg value="jdk.nashorn.internal.objects"/> + <arg value="${basedir}/build/classes"/> + </java> + + <move todir="${basedir}/build/classes/jdk/nashorn/internal/objects"> + <fileset dir="${basedir}/build/classes/jdk/nashorn/internal/objects"/> + <mapper type="glob" from="*.class" to="*.clazz"/> + </move> + </target> + + <target name="run-nasgen-eclipse"> + <mkdir dir="${basedir}/build/eclipse/.nasgentmp"/> + + <java classname="jdk.nashorn.internal.tools.nasgen.Main" fork="true" failonerror="true"> + <classpath> + <pathelement location="${basedir}/buildtools/nasgen/dist/nasgen.jar"/> + <pathelement path="${basedir}/build/eclipse"/> + </classpath> + <arg value="${basedir}/build/eclipse"/> + <arg value="jdk.nashorn.internal.objects"/> + <arg value="${basedir}/build/eclipse/.nasgentmp"/> + </java> + + <move todir="${basedir}/build/eclipse/jdk/nashorn/internal/objects"> + <fileset dir="${basedir}/build/eclipse/.nasgentmp/jdk/nashorn/internal/objects"> + <include name="*.class"/> + </fileset> + <mapper type="glob" from="*.class" to="*.clazz"/> + </move> + + <delete includeemptydirs="true"><fileset dir="${basedir}/build/eclipse/.nasgentmp" includes="**"/></delete> + + <copy todir="${basedir}/build/eclipse/jdk/nashorn/internal/objects" preservelastmodified="true"> + <fileset dir="${basedir}/build/eclipse/jdk/nashorn/internal/objects"> + <include name="**/*.class"/> + </fileset> + <mapper type="glob" from="*.class" to="*.clazz"/> + </copy> + </target> + + <target name="clean-nasgen"> + <ant inheritAll="false" dir="${basedir}/buildtools/nasgen" + antfile="build.xml" target="clean"/> + </target> + +</project> diff --git a/make/build.xml b/make/build.xml new file mode 100644 index 00000000..79669a80 --- /dev/null +++ b/make/build.xml @@ -0,0 +1,355 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + or visit www.oracle.com if you need additional information or have any + questions. +--> +<project name="nashorn" default="all" basedir=".."> + <import file="build-nasgen.xml"/> + <import file="build-benchmark.xml"/> + + <target name="init"> + <loadproperties srcFile="make/project.properties"/> + <path id="nashorn.ext.path"> + <pathelement location="${dist.dir}"/> + </path> + <property name="ext.class.path" value="-Djava.ext.dirs="${toString:nashorn.ext.path}""/> + </target> + + <target name="prepare" depends="init"> + <mkdir dir="${build.dir}"/> + <mkdir dir="${build.classes.dir}"/> + <mkdir dir="${build.classes.dir}/META-INF/services"/> + <mkdir dir="${build.test.classes.dir}"/> + <mkdir dir="${dist.dir}"/> + <mkdir dir="${dist.javadoc.dir}"/> + <!-- check if JDK already has ASM classes --> + <available property="asm.available" classname="jdk.internal.org.objectweb.asm.Type"/> + <!-- check if testng.jar is avaiable --> + <available property="testng.available" file="${file.reference.testng.jar}"/> + </target> + + <target name="clean" depends="init, clean-nasgen"> + <delete includeemptydirs="true"> + <fileset dir="${build.dir}" excludes="${dynalink.dir.name}/**/*" erroronmissingdir="false"/> + </delete> + <delete dir="${dist.dir}"/> + </target> + + <target name="clean-dynalink"> + <delete dir="${dynalink.dir}"/> + </target> + + <target name="clean-all" depends="clean-dynalink, clean"> + <delete dir="${build.dir}"/> + </target> + + <!-- do it only if ASM is not available --> + <target name="compile-asm" depends="prepare" unless="asm.available"> + <javac srcdir="${asm.src.dir}" + destdir="${build.classes.dir}" + excludes="**/optimizer/* **/xml/* **/attrs/*" + source="${javac.source}" + target="${javac.target}" + debug="${javac.debug}" + encoding="${javac.encoding}" + includeantruntime="false"/> + </target> + + <target name="check-dynalink-uptodate" depends="init"> + <property name="versioned.dynalink.jar" value="${dynalink.dir}/dynalink-${dynalink.jar.version}.jar"/> + <condition property="dynalink.uptodate"> + <and> + <available file="${versioned.dynalink.jar}"/> + <filesmatch file1="${versioned.dynalink.jar}" file2="${dynalink.jar}"/> + </and> + </condition> + </target> + + <target name="get-dynalink" depends="check-dynalink-uptodate" unless="dynalink.uptodate"> + <mkdir dir="${dynalink.dir}"/> + <!-- Delete previous snapshots, if any --> + <delete> + <fileset dir="${dynalink.dir}" includes="*"/> + </delete> + <property name="dynalink.download.base.url" value="http://oss.sonatype.org/content/repositories/${dynalink.version.type}s/org/dynalang/dynalink/${dynalink.version}/dynalink-${dynalink.jar.version}"/> + <get src="${dynalink.download.base.url}.jar" dest="${versioned.dynalink.jar}" usetimestamp="true"/> + <get src="${dynalink.download.base.url}-sources.jar" dest="${dynalink.dir}/dynalink-sources.jar" usetimestamp="true"/> + <copy file="${versioned.dynalink.jar}" tofile="${dynalink.jar}" overwrite="true"/> + </target> + + <target name="compile" depends="compile-asm, get-dynalink" description="Compiles nashorn"> + <javac srcdir="${src.dir}" + destdir="${build.classes.dir}" + classpath="${javac.classpath}" + source="${javac.source}" + target="${javac.target}" + debug="${javac.debug}" + encoding="${javac.encoding}" + includeantruntime="false"> + <compilerarg value="-Xlint:unchecked"/> + <compilerarg value="-Xlint:deprecation"/> + <compilerarg value="-XDignore.symbol.file"/> + </javac> + <copy todir="${build.classes.dir}/META-INF/services"> + <fileset dir="${meta.inf.dir}/services/"/> + </copy> + <copy todir="${build.classes.dir}/jdk/nashorn/api/scripting/resources"> + <fileset dir="${src.dir}/jdk/nashorn/api/scripting/resources/"/> + </copy> + <copy todir="${build.classes.dir}/jdk/nashorn/internal/runtime/resources"> + <fileset dir="${src.dir}/jdk/nashorn/internal/runtime/resources/"/> + </copy> + <copy todir="${build.classes.dir}/jdk/nashorn/tools/resources"> + <fileset dir="${src.dir}/jdk/nashorn/tools/resources/"/> + </copy> + <echo message="full=${nashorn.fullversion}" file="${build.classes.dir}/jdk/nashorn/internal/runtime/resources/version.properties"/> + <echo file="${build.classes.dir}/jdk/nashorn/internal/runtime/resources/version.properties" append="true">${line.separator}</echo> + <echo message="release=${nashorn.version}" file="${build.classes.dir}/jdk/nashorn/internal/runtime/resources/version.properties" append="true"/> + </target> + + <target name="jar" depends="compile, run-nasgen" description="Creates nashorn.jar"> + <jar jarfile="${dist.jar}" manifest="${meta.inf.dir}/MANIFEST.MF" index="true" filesetmanifest="merge"> + <fileset dir="${build.classes.dir}"/> + <zipfileset src="${dynalink.jar}"/> + <manifest> + <attribute name="Archiver-Version" value="n/a"/> + <attribute name="Build-Jdk" value="${java.runtime.version}"/> + <attribute name="Built-By" value="n/a"/> + <attribute name="Created-By" value="Ant jar task"/> + <section name="jdk/nashorn/"> + <attribute name="Implementation-Title" value="${nashorn.product.name}"/> + <attribute name="Implementation-Version" value="${nashorn.version}"/> + </section> + </manifest> + </jar> + </target> + + <target name="javadoc" depends="compile-asm"> + <javadoc destdir="${dist.javadoc.dir}" private="yes" use="yes" overview="src/overview.html" windowtitle="${nashorn.product.name} ${nashorn.version}"> + <classpath> + <pathelement location="${build.classes.dir}"/> + <pathelement location="${dynalink.jar}"/> + </classpath> + <fileset dir="${src.dir}" includes="**/*.java"/> + <link href="http://docs.oracle.com/javase/7/docs/api"/> + <link href="http://szegedi.github.com/dynalink/0.4/javadoc"/> + </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"> + <jvmarg line="${ext.class.path}"/> + <arg value="-scripting"/> + <arg value="docs/genshelldoc.js"/> + </java> + </target> + + <!-- generate all docs --> + <target name="docs" depends="javadoc, shelldoc"/> + + <!-- create .zip and .tar.gz for nashorn binaries and scripts. --> + <target name="dist" depends="jar"> + <zip destfile="${build.zip}" basedir=".." + excludes="nashorn/bin/*.sh" includes="nashorn/bin/** nashorn/dist/**"/> + <tar destfile="${build.gzip}" basedir=".." compression="gzip" + excludes="nashorn/bin/*.sh" includes="nashorn/bin/** nashorn/dist/**"/> + </target> + + <target name="compile-test" depends="compile, run-nasgen" if="testng.available"> + <!-- testng task --> + <taskdef name="testng" classname="org.testng.TestNGAntTask" + classpath="${file.reference.testng.jar}"/> + + <javac srcdir="${test.src.dir}" + destdir="${build.test.classes.dir}" + classpath="${javac.test.classpath}" + source="${javac.source}" + target="${javac.target}" + debug="${javac.debug}" + encoding="${javac.encoding}" + includeantruntime="false"/> + </target> + + <target name="generate-policy-file"> + <!-- Generating nashorn.policy file --> + <echo message="grant codeBase "file:/${basedir}/dist/nashorn.jar" {" file="${build.dir}/nashorn.policy"/> + <echo message="" file="${build.dir}/nashorn.policy" append="true"/> + <echo message="permission java.security.AllPermission;" file="${build.dir}/nashorn.policy" append="true"/> + <echo message="" file="${build.dir}/nashorn.policy" append="true"/> + <echo message="};" file="${build.dir}/nashorn.policy" append="true"/> + <echo message="" file="${build.dir}/nashorn.policy" append="true"/> + + <echo message="grant codeBase "file:/${basedir}/build/test/classes" {" file="${build.dir}/nashorn.policy" append="true"/> + <echo message="" file="${build.dir}/nashorn.policy" append="true"/> + <echo message=" permission java.security.AllPermission;" file="${build.dir}/nashorn.policy" append="true"/> + <echo message="" file="${build.dir}/nashorn.policy" append="true"/> + <echo message="};" file="${build.dir}/nashorn.policy" append="true"/> + <echo message="" file="${build.dir}/nashorn.policy" append="true"/> + + <echo message="grant codeBase "file:/${basedir}/${file.reference.testng.jar}" {" file="${build.dir}/nashorn.policy" append="true"/> + <echo message="" file="${build.dir}/nashorn.policy" append="true"/> + <echo message=" permission java.security.AllPermission;" file="${build.dir}/nashorn.policy" append="true"/> + <echo message="" file="${build.dir}/nashorn.policy" append="true"/> + <echo message="};" file="${build.dir}/nashorn.policy" append="true"/> + <echo message="" file="${build.dir}/nashorn.policy" append="true"/> + + <echo message="grant codeBase "file:/${basedir}/test/script/basic/*" {" file="${build.dir}/nashorn.policy" append="true"/> + <echo message="" file="${build.dir}/nashorn.policy" append="true"/> + <echo message=" permission java.security.AllPermission;" file="${build.dir}/nashorn.policy" append="true"/> + <echo message="" file="${build.dir}/nashorn.policy" append="true"/> + <echo message="};" file="${build.dir}/nashorn.policy" append="true"/> + <echo message="" file="${build.dir}/nashorn.policy" append="true"/> + + <echo message="grant codeBase "file:/${basedir}/test/perf/*" {" file="${build.dir}/nashorn.policy" append="true"/> + <echo message="" file="${build.dir}/nashorn.policy" append="true"/> + <echo message=" permission java.security.AllPermission;" file="${build.dir}/nashorn.policy" append="true"/> + <echo message="" file="${build.dir}/nashorn.policy" append="true"/> + <echo message="};" file="${build.dir}/nashorn.policy" append="true"/> + <echo message="" file="${build.dir}/nashorn.policy" append="true"/> + + <replace file="${build.dir}/nashorn.policy"><replacetoken>\</replacetoken><replacevalue>/</replacevalue></replace> <!--hack for Windows - to make URLs with normal path separators --> + <replace file="${build.dir}/nashorn.policy"><replacetoken>//</replacetoken><replacevalue>/</replacevalue></replace> <!--hack for Unix - to avoid leading // in URLs --> + + </target> + + <target name="check-external-tests"> + <available file="${test.external.dir}/prototype" property="test-sys-prop.external.prototype"/> + <available file="${test.external.dir}/sunspider" property="test-sys-prop.external.sunspider"/> + <available file="${test.external.dir}/underscore" property="test-sys-prop.external.underscore"/> + <available file="${test.external.dir}/octane" property="test-sys-prop.external.octane"/> + <available file="${test.external.dir}/yui" property="test-sys-prop.external.yui"/> + <available file="${test.external.dir}/jquery" property="test-sys-prop.external.jquery"/> + <available file="${test.external.dir}/test262" property="test-sys-prop.external.test262"/> + </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."/> + </target> + + <target name="test" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file" if="testng.available"> + <java classname="${nashorn.shell.tool}" fork="true" dir="${test.script.dir}/representations" output="${build.dir}/output1.log" error="${build.dir}/err.log"> + <jvmarg line="${ext.class.path}"/> + <jvmarg line="-Dnashorn.fields.dual=true"/> + <arg value="NASHORN-592a.js"/> + </java> + <java classname="${nashorn.shell.tool}" fork="true" dir="${test.script.dir}/representations" output="${build.dir}/output2.log" error="${build.dir}/err.log"> + <jvmarg line="${ext.class.path}"/> + <arg value="NASHORN-592a.js"/> + </java> + <condition property="representation-ok"> + <filesmatch file1="${build.dir}/output1.log" file2="${build.dir}/output2.log"/> + </condition> + <fail unless="representation-ok">Representation test failed - output differs!</fail> + <fileset id="test.classes" dir="${build.test.classes.dir}"> + <include name="**/access/*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="**/framework/*Test.class"/> + </fileset> + + <testng outputdir="${build.test.results.dir}" classfilesetref="test.classes" + verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}"> + <jvmarg line="${ext.class.path}"/> + <jvmarg line="${run.test.jvmargs} ${run.test.jvmsecurityargs}"/> + <propertyset> + <propertyref prefix="test-sys-prop."/> + <mapper from="test-sys-prop.*" to="*" type="glob"/> + </propertyset> + <classpath> + <pathelement path="${run.test.classpath}"/> + </classpath> + </testng> + </target> + + <target name="test-basicparallel" depends="jar, check-testng, check-external-tests, compile-test, generate-policy-file"> + <!-- use just build.test.classes.dir to avoid referring to TestNG --> + <java classname="${parallel.test.runner}" dir="${basedir}" classpath="${build.test.classes.dir}" failonerror="true" fork="true"> + <jvmarg line="${ext.class.path}"/> + <jvmarg line="${run.test.jvmargs} ${run.test.jvmsecurityargs}"/> + <syspropertyset> + <propertyref prefix="test-sys-prop."/> + <mapper type="glob" from="test-sys-prop.*" to="*"/> + </syspropertyset> + </java> + </target> + + <target name="test262" depends="jar, check-testng, check-external-tests, compile-test" if="testng.available"> + <fileset id="test.classes" dir="${build.test.classes.dir}"> + <include name="**/framework/*Test.class"/> + </fileset> + + <testng outputdir="${build.test.results.dir}" classfilesetref="test.classes" + verbose="${testng.verbose}" haltonfailure="true" useDefaultListeners="false" listeners="${testng.listeners}" workingDir="${basedir}"> + <jvmarg line="${ext.class.path}"/> + <jvmarg line="${run.test.jvmargs}"/> + <propertyset> + <propertyref prefix="test262-test-sys-prop."/> + <mapper from="test262-test-sys-prop.*" to="*" type="glob"/> + </propertyset> + <classpath> + <pathelement path="${run.test.classpath}"/> + </classpath> + </testng> + </target> + + <target name="test262parallel" depends="test262-parallel"/> + + <target name="test262-parallel" depends="jar, check-testng, check-external-tests, compile-test" if="testng.available"> + <!-- use just build.test.classes.dir to avoid referring to TestNG --> + <java classname="${parallel.test.runner}" dir="${basedir}" classpath="${build.test.classes.dir}" fork="true"> + <jvmarg line="${ext.class.path}"/> + <jvmarg line="${run.test.jvmargs}"/> + <syspropertyset> + <propertyref prefix="test262-test-sys-prop."/> + <mapper type="glob" from="test262-test-sys-prop.*" to="*"/> + </syspropertyset> + </java> + </target> + + <target name="all" depends="test, docs" + description="Build, test and generate docs for nashorn"/> + + <target name="run" depends="jar" + description="Run the shell with a sample script"> + <java classname="${nashorn.shell.tool}" fork="true" dir="samples"> + <jvmarg line="${ext.class.path}"/> + <jvmarg line="${run.test.jvmargs}"/> + <arg value="-dump-on-error"/> + <arg value="test.js"/> + </java> + </target> + + <target name="debug" depends="jar" + description="Debug the shell with a sample script"> + <java classname="${nashorn.shell.tool}" fork="true" dir="samples"> + <jvmarg line="${ext.class.path}"/> + <jvmarg line="${run.test.jvmargs}"/> + <arg value="--print-code"/> + <arg value="--verify-code"/> + <arg value="--print-symbols"/> + <jvmarg value="-Dnashorn.codegen.debug=true"/> + <arg value="test.js"/> + </java> + </target> +</project> diff --git a/make/nbproject/ide-file-targets.xml b/make/nbproject/ide-file-targets.xml new file mode 100644 index 00000000..3a957ccd --- /dev/null +++ b/make/nbproject/ide-file-targets.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + or visit www.oracle.com if you need additional information or have any + questions. +--> +<project basedir=".." name="nashorn-IDE"> + <property file="nbproject/nbjdk.properties"/> + <property location="${netbeans.user}/build.properties" name="user.properties.file"/> + <property file="${user.properties.file}"/> + <import file="jdk.xml"/> + <import file="${basedir}/build-init.xml"/> + <!-- TODO: edit the following target according to your needs --> + <!-- (more info: http://www.netbeans.org/kb/articles/freeform-config.html#runsingle) --> + <target depends="-jdk-init, init" name="debug-selected-file-in-src"> + <fail unless="debug.class">Must set property 'debug.class'</fail> + <ant antfile="build.xml" inheritall="false" target="jar"/> + <nbjpdastart addressproperty="jpda.address" name="nashorn" transport="dt_socket"> + <classpath path="${run.test.classpath}"/> + </nbjpdastart> + <java classname="${debug.class}" fork="false"> + <classpath path="${run.test.classpath}"/> + <jvmarg line="${boot.class.path}"/> + <jvmarg value="-Xdebug"/> + <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/> + <jvmarg line="${run.test.jvmargs}"/> + <arg value="${debug.class}"/> + </java> + </target> + <!-- TODO: edit the following target according to your needs --> + <!-- (more info: http://www.netbeans.org/kb/articles/freeform-config.html#runsingle) --> + <target depends="-jdk-init, init" name="run-selected-file-in-src"> + <fail unless="run.class">Must set property 'run.class'</fail> + <ant antfile="build.xml" inheritall="false" target="jar"/> + <java classname="${run.class}" failonerror="true" fork="false"> + <classpath path="${run.test.classpath}"/> + <jvmarg line="${boot.class.path}"/> + <jvmarg line="${run.test.jvmargs}"/> + <arg value="${run.class}"/> + </java> + </target> +</project> diff --git a/make/nbproject/ide-targets.xml b/make/nbproject/ide-targets.xml new file mode 100644 index 00000000..281672d8 --- /dev/null +++ b/make/nbproject/ide-targets.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + or visit www.oracle.com if you need additional information or have any + questions. +--> + +<project basedir="../.." name="nashorn-IDE"> + <import file="../build.xml"/> + <!-- TODO: edit the following target according to your needs --> + <!-- (more info: http://www.netbeans.org/kb/articles/freeform-config.html#debugj2se) --> + <target depends="jar" description="Run the shell with a sample script" name="debug-nb"> + <nbjpdastart addressproperty="jpda.address" name="nashorn" transport="dt_socket"> + <classpath path="${run.test.classpath}"/> + </nbjpdastart> + <java classname="jdk.nashorn.tools.Shell" classpath="${run.test.classpath}" dir="samples" fork="true"> + <jvmarg line="${ext.class.path}"/> + <jvmarg line="${run.test.jvmargs}"/> + <arg value="test.js"/> + <jvmarg value="-Xdebug"/> + <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/> + </java> + </target> +</project> diff --git a/make/nbproject/jdk.xml b/make/nbproject/jdk.xml new file mode 100644 index 00000000..b6fa7ebb --- /dev/null +++ b/make/nbproject/jdk.xml @@ -0,0 +1,179 @@ +<?xml version="1.0" encoding="UTF-8"?><project name="jdk" basedir="."> +<!-- + Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + or visit www.oracle.com if you need additional information or have any + questions. +--> + + + <description> + Permits selection of a JDK to use when building and running project. + See: http://www.netbeans.org/issues/show_bug.cgi?id=64160 + </description> + + <target name="-jdk-pre-preinit"> + <condition property="nbjdk.active-or-nbjdk.home"> + <or> + <and> + <isset property="nbjdk.active"/> + <not> + <equals arg1="${nbjdk.active}" arg2="default_platform"/> + </not> + </and> + <and> + <isset property="nbjdk.home"/> + <not> + <isset property="nbjdk.home.defaulted"/> + </not> + </and> + </or> + </condition> + </target> + + <target xmlns:common="http://java.netbeans.org/freeform/jdk.xml" name="-jdk-preinit" depends="-jdk-pre-preinit" if="nbjdk.active-or-nbjdk.home"> + <macrodef name="property" uri="http://java.netbeans.org/freeform/jdk.xml"> + <attribute name="name"/> + <attribute name="value"/> + <sequential> + <property name="@{name}" value="${@{value}}"/> + </sequential> + </macrodef> + <common:property name="nbjdk.home" value="platforms.${nbjdk.active}.home"/> + <common:property name="nbjdk.javac.tmp" value="platforms.${nbjdk.active}.javac"/> + <condition property=".exe" value=".exe"> + <os family="windows"/> + </condition> + <property name=".exe" value=""/> + <condition property="nbjdk.javac" value="${nbjdk.home}/bin/javac${.exe}"> + <equals arg1="${nbjdk.javac.tmp}" arg2="$${platforms.${nbjdk.active}.javac}"/> + </condition> + <property name="nbjdk.javac" value="${nbjdk.javac.tmp}"/> + <common:property name="nbjdk.java.tmp" value="platforms.${nbjdk.active}.java"/> + <condition property="nbjdk.java" value="${nbjdk.home}/bin/java${.exe}"> + <equals arg1="${nbjdk.java.tmp}" arg2="$${platforms.${nbjdk.active}.java}"/> + </condition> + <property name="nbjdk.java" value="${nbjdk.java.tmp}"/> + <common:property name="nbjdk.javadoc.tmp" value="platforms.${nbjdk.active}.javadoc"/> + <condition property="nbjdk.javadoc" value="${nbjdk.home}/bin/javadoc${.exe}"> + <equals arg1="${nbjdk.javadoc.tmp}" arg2="$${platforms.${nbjdk.active}.javadoc}"/> + </condition> + <property name="nbjdk.javadoc" value="${nbjdk.javadoc.tmp}"/> + <common:property name="nbjdk.bootclasspath.tmp" value="platforms.${nbjdk.active}.bootclasspath"/> + <condition property="nbjdk.bootclasspath" value="${nbjdk.home}/jre/lib/rt.jar"> + <equals arg1="${nbjdk.bootclasspath.tmp}" arg2="$${platforms.${nbjdk.active}.bootclasspath}"/> + </condition> + <property name="nbjdk.bootclasspath" value="${nbjdk.bootclasspath.tmp}"/> + <condition property="nbjdk.valid"> + <and> + <available file="${nbjdk.home}" type="dir"/> + <available file="${nbjdk.javac}" type="file"/> + <available file="${nbjdk.java}" type="file"/> + <available file="${nbjdk.javadoc}" type="file"/> + + </and> + </condition> + <echo level="verbose">nbjdk.active=${nbjdk.active} nbjdk.home=${nbjdk.home} nbjdk.java=${nbjdk.java} nbjdk.javac=${nbjdk.javac} nbjdk.javadoc=${nbjdk.javadoc} nbjdk.bootclasspath=${nbjdk.bootclasspath} nbjdk.valid=${nbjdk.valid} have-jdk-1.4=${have-jdk-1.4} have-jdk-1.5=${have-jdk-1.5}</echo> + </target> + + <target name="-jdk-warn" depends="-jdk-preinit" if="nbjdk.active-or-nbjdk.home" unless="nbjdk.valid"> + <property name="jdkhome.presumed" location="${java.home}/.."/> + <echo level="warning">Warning: nbjdk.active=${nbjdk.active} or nbjdk.home=${nbjdk.home} is an invalid Java platform; ignoring and using ${jdkhome.presumed}</echo> + </target> + + <target name="-jdk-presetdef-basic" depends="-jdk-preinit" if="nbjdk.valid" unless="nbjdk.presetdef.basic.done"> + + + <macrodef name="javac-presetdef"> + <attribute name="javacval"/> + <sequential> + <presetdef name="javac"> + <javac fork="yes" executable="@{javacval}"/> + </presetdef> + </sequential> + </macrodef> + <javac-presetdef javacval="${nbjdk.javac}"/> + <macrodef name="java-presetdef"> + <attribute name="javaval"/> + <sequential> + <presetdef name="java"> + <java fork="yes" jvm="@{javaval}"/> + </presetdef> + </sequential> + </macrodef> + <java-presetdef javaval="${nbjdk.java}"/> + <macrodef name="javadoc-presetdef"> + <attribute name="javadocval"/> + <sequential> + <presetdef name="javadoc"> + <javadoc executable="@{javadocval}"/> + </presetdef> + </sequential> + </macrodef> + <javadoc-presetdef javadocval="${nbjdk.javadoc}"/> + <macrodef name="junit-presetdef"> + <attribute name="javaval"/> + <sequential> + <presetdef name="junit"> + <junit fork="yes" jvm="@{javaval}"/> + </presetdef> + </sequential> + </macrodef> + <junit-presetdef javaval="${nbjdk.java}"/> + <property name="nbjdk.presetdef.basic.done" value="true"/> + </target> + + <target name="-jdk-presetdef-nbjpdastart" depends="-jdk-preinit" if="nbjdk.valid" unless="nbjdk.presetdef.nbjpdastart.done"> + <macrodef name="nbjpdastart-presetdef"> + <attribute name="bootcpval"/> + <sequential> + <presetdef name="nbjpdastart"> + <nbjpdastart> + <bootclasspath> + <path path="@{bootcpval}"/> + </bootclasspath> + </nbjpdastart> + </presetdef> + </sequential> + </macrodef> + <nbjpdastart-presetdef bootcpval="${nbjdk.bootclasspath}"/> + <property name="nbjdk.presetdef.nbjpdastart.done" value="true"/> + </target> + + <target name="-jdk-default" unless="nbjdk.active-or-nbjdk.home"> + + <property name="java.home.parent" location="${java.home}/.."/> + <condition property="nbjdk.home" value="${java.home.parent}"> + <available file="${java.home.parent}/lib/tools.jar" type="file"/> + </condition> + <condition property="nbjdk.home" value="${java.home}"> + <available file="${java.home}/lib/tools.jar" type="file"/> + </condition> + + <condition property="nbjdk.home" value="/Library/Java/Home"> + <available file="/Library/Java/Home" type="dir"/> + </condition> + + <property name="nbjdk.home" location="${java.home.parent}"/> + <property name="nbjdk.home.defaulted" value="true"/> + </target> + + <target name="-jdk-init" depends="-jdk-preinit,-jdk-warn,-jdk-presetdef-basic,-jdk-default"/> + +</project>
\ No newline at end of file diff --git a/make/nbproject/nbjdk.properties b/make/nbproject/nbjdk.properties new file mode 100644 index 00000000..6260c35a --- /dev/null +++ b/make/nbproject/nbjdk.properties @@ -0,0 +1,24 @@ +# +# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +nbjdk.active=JDK_1.8 + diff --git a/make/nbproject/nbjdk.xml b/make/nbproject/nbjdk.xml new file mode 100644 index 00000000..cbd7af38 --- /dev/null +++ b/make/nbproject/nbjdk.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + or visit www.oracle.com if you need additional information or have any + questions. +--> +<project basedir=".."> + <property file="../global.properties"/> + <property file="nbproject/nbjdk.properties"/> + <property location="${netbeans.user}/build.properties" name="user.properties.file"/> + <property file="${user.properties.file}"/> + <import file="jdk.xml"/> + <target depends="-jdk-init" name="jar"> + <ant inheritall="false" target="jar"/> + </target> + <target depends="-jdk-init" name="clean"> + <ant inheritall="false" target="clean"/> + </target> + <target depends="-jdk-init" name="javadoc"> + <ant inheritall="false" target="javadoc"/> + </target> + <target depends="-jdk-init" name="test"> + <ant inheritall="false" target="test"/> + </target> + <target depends="-jdk-init" name="run"> + <ant inheritall="false" target="run"/> + </target> + <target depends="-jdk-init,-jdk-presetdef-nbjpdastart" name="debug-nb"> + <ant antfile="nbproject/ide-targets.xml" inheritall="false" target="debug-nb"/> + </target> +</project> diff --git a/make/nbproject/project.xml b/make/nbproject/project.xml new file mode 100644 index 00000000..ee88965a --- /dev/null +++ b/make/nbproject/project.xml @@ -0,0 +1,177 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + + This code is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License version 2 only, as + published by the Free Software Foundation. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + or visit www.oracle.com if you need additional information or have any + questions. +--> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.ant.freeform</type> + <configuration> + <general-data xmlns="http://www.netbeans.org/ns/freeform-project/1"> + <name>nashorn</name> + </general-data> + <general-data xmlns="http://www.netbeans.org/ns/freeform-project/2"> + <!-- Do not use Project Properties customizer when editing this file manually. --> + <name>nashorn</name> + <properties/> + <folders> + <source-folder> + <label>nashorn</label> + <location>.</location> + <encoding>UTF-8</encoding> + </source-folder> + <source-folder> + <label>../src</label> + <location>../src</location> + </source-folder> + <source-folder> + <label>../test/src</label> + <location>../test/src</location> + </source-folder> + <source-folder> + <label>../buildtools/nasgen/src</label> + <location>../buildtools/nasgen/src</location> + </source-folder> + <source-folder> + <label>../test/src</label> + <type>java</type> + <location>../test/src</location> + <encoding>UTF-8</encoding> + </source-folder> + <source-folder> + <label>../src</label> + <type>java</type> + <location>../src</location> + <encoding>UTF-8</encoding> + </source-folder> + <source-folder> + <label>../buildtools/nasgen/src</label> + <type>java</type> + <location>../buildtools/nasgen/src</location> + <encoding>UTF-8</encoding> + </source-folder> + </folders> + <ide-actions> + <action name="build"> + <script>nbproject/nbjdk.xml</script> + <target>jar</target> + </action> + <action name="clean"> + <script>nbproject/nbjdk.xml</script> + <target>clean</target> + </action> + <action name="javadoc"> + <script>nbproject/nbjdk.xml</script> + <target>javadoc</target> + </action> + <action name="test"> + <script>nbproject/nbjdk.xml</script> + <target>test</target> + </action> + <action name="rebuild"> + <script>nbproject/nbjdk.xml</script> + <target>clean</target> + <target>jar</target> + </action> + <action name="run"> + <script>nbproject/nbjdk.xml</script> + <target>run</target> + </action> + <action name="debug"> + <script>nbproject/nbjdk.xml</script> + <target>debug-nb</target> + </action> + <action name="debug.single"> + <script>nbproject/ide-file-targets.xml</script> + <target>debug-selected-file-in-src</target> + <context> + <property>debug.class</property> + <folder>test/src</folder> + <pattern>\.java$</pattern> + <format>java-name</format> + <arity> + <one-file-only/> + </arity> + </context> + </action> + <action name="run.single"> + <script>nbproject/ide-file-targets.xml</script> + <target>run-selected-file-in-src</target> + <context> + <property>run.class</property> + <folder>test/src</folder> + <pattern>\.java$</pattern> + <format>java-name</format> + <arity> + <one-file-only/> + </arity> + </context> + </action> + </ide-actions> + <view> + <items> + <source-folder style="packages"> + <label>../test/src</label> + <location>../test/src</location> + </source-folder> + <source-folder style="packages"> + <label>../src</label> + <location>../src</location> + </source-folder> + <source-folder style="packages"> + <label>../buildtools/nasgen/src</label> + <location>../buildtools/nasgen/src</location> + </source-folder> + <source-file> + <location>build.xml</location> + </source-file> + </items> + <context-menu> + <ide-action name="build"/> + <ide-action name="rebuild"/> + <ide-action name="clean"/> + <ide-action name="javadoc"/> + <ide-action name="run"/> + <ide-action name="test"/> + <ide-action name="debug"/> + </context-menu> + </view> + <subprojects/> + </general-data> + <java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/3"> + <compilation-unit> + <package-root>../test/src</package-root> + <unit-tests/> + <classpath mode="compile">../test/lib/testng.jar:../build/classes:../src</classpath> + <source-level>1.7</source-level> + </compilation-unit> + <compilation-unit> + <package-root>../src</package-root> + <classpath mode="compile">../build/dynalink/dynalink.jar</classpath> + <source-level>1.7</source-level> + </compilation-unit> + <compilation-unit> + <package-root>../buildtools/nasgen/src</package-root> + <classpath mode="compile">../build/classes:../src</classpath> + <source-level>1.7</source-level> + </compilation-unit> + </java-data> + </configuration> +</project> diff --git a/make/project.properties b/make/project.properties new file mode 100644 index 00000000..64ec4083 --- /dev/null +++ b/make/project.properties @@ -0,0 +1,223 @@ +# +# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +application.title=nashorn + +# source and target levels +build.compiler=modern +javac.source=1.7 +javac.target=1.7 + +# nashorn version information +nashorn.version=0.1 +nashorn.fullversion=0.1 +nashorn.product.name=Oracle Nashorn + +# This directory is removed when the project is cleaned: +build.dir=build +build.classes.dir=${build.dir}/classes +build.zip=${build.dir}/nashorn.zip +build.gzip=${build.dir}/nashorn.tar.gz + +# nashorn Shell tool +nashorn.shell.tool=jdk.nashorn.tools.Shell + +# nasgen tool +nasgen.tool=jdk.nashorn.internal.tools.nasgen.Main + +# parallel test runner tool +parallel.test.runner=jdk.nashorn.internal.test.framework.ParallelTestRunner + +# test classes directory +build.test.classes.dir=${build.dir}/test/classes +# test results directory +build.test.results.dir=${build.dir}/test/reports + +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/nashorn.jar +dist.javadoc.dir=${dist.dir}/javadoc + +# directory where asm project lives +asm.dir=../asm +asm.src.dir=${asm.dir}/src + +# jars refererred +file.reference.testng.jar=test/lib/testng.jar + +# Set testng verbose level +# From TestNG docs: "the verbosity level (0 to 10 where 10 is most detailed) +# Actually, this is a lie: you can specify -1 and this will put TestNG in +# debug mode (no longer slicing off stack traces and all)." + +testng.verbose=2 + +# TestNG listeners - we want to replace TestNG's own JUnit +# reporter, but want everything else provided by default +# Unfortunately, we've to clone the other default reporters here. + +testng.listeners=\ + org.testng.reporters.SuiteHTMLReporter, \ + org.testng.reporters.jq.Main, \ + org.testng.reporters.FailedReporter, \ + org.testng.reporters.XMLReporter \ + org.testng.reporters.EmailableReporter, \ + jdk.nashorn.internal.test.framework.JSJUnitReportReporter + +# Define the version of Dynalink that is used. Version types are either +# 'snapshot' or 'release'. When it is 'snapshot', the version must have +# "-SNAPSHOT" suffix and the jar version will have a timestamp in it. When +# it's 'release', the version has no suffix, and the jar version is +# identical to version - fun with Maven central. +dynalink.version=0.5-SNAPSHOT +dynalink.version.type=snapshot +dynalink.jar.version=0.5-20121218.140128-11 +dynalink.dir.name=dynalink +dynalink.dir=build/${dynalink.dir.name} +dynalink.jar=${dynalink.dir}/dynalink.jar + +javac.debug=true +javac.encoding=ascii +javac.classpath=\ + ${build.classes.dir}:\ + ${dynalink.jar} +javac.test.classpath=\ + ${build.classes.dir}:\ + ${build.test.classes.dir}:\ + ${file.reference.testng.jar} + +meta.inf.dir=${src.dir}/META-INF + +run.classpath=\ + ${build.classes.dir} + +# test scripts to run +test.dir=test +test.script.dir=test/script +test.basic.dir=test/script/basic +test.error.dir=test/script/error +test.sandbox.dir=test/script/sandbox +test.external.dir=test/script/external +test262.dir=${test.external.dir}/test262 +test262.suite.dir=${test262.dir}/test/suite + +test-sys-prop.test.dir=${test.dir} +test-sys-prop.test.js.roots=${test.basic.dir} ${test.error.dir} ${test.sandbox.dir} +test-sys-prop.test262.suite.dir=${test262.suite.dir} +test-sys-prop.es5conform.testcases.dir=${test.external.dir}/ES5Conform/TestCases +test-sys-prop.test.basic.dir=${test.basic.dir} + +# framework root for our script tests +test-sys-prop.test.js.framework=${test.script.dir}/assert.js + +# Control the verbosity of ParserTest +test-sys-prop.parsertest.verbose=false + +# turn on/off scripting mode for parser tests +test-sys-prop.parsertest.scripting=true + +# turn on/off test262 scripts for parser tests +test-sys-prop.parsertest.test262=false + +# Control the verbosity of the CompilerTest +test-sys-prop.compilertest.verbose=false + +# turn on/off scripting mode for compiler tests +test-sys-prop.compilertest.scripting=true + +# turn on/off test262 scripts for compiler tests +test-sys-prop.compilertest.test262=false + +# test directory to be excluded. +test-sys-prop.test.js.exclude.dir=${test.script.dir}/currently-failing ${test.external.dir} + +# run everything that's js in here, without checking file headers for test annotations +test-sys-prop.test.js.unchecked.dir=${test262.dir} + +# test root for octane +octane-test-sys-prop.test.js.roots=${test.external.dir}/octane/benchmarks + +# framework root for octane +octane-test-sys-prop.test.js.framework=${test.basic.dir}/run-octane.js + +# list of tests to be excluded +octane-test-sys-prop.test.js.exclude.list=base.js + +# test root for sunspider +sunspider-test-sys-prop.test.js.roots=${test.external.dir}/sunspider/ + +# framework root for sunspider +sunspider-test-sys-prop.test.js.framework=${test.basic.dir}/runsunspider.js + +# list of tests to be excluded +sunspider-test-sys-prop.test.js.exclude.list= + +# execute our script tests in shared nashorn context or not? +test-sys-prop.test.js.shared.context=false + +# execute test262 tests in shared nashorn context or not? +test262-test-sys-prop.test.js.shared.context=true + +# test262 test root +test262-test-sys-prop.test.js.roots=${test262.suite.dir} +# test262 enable/disable strict mode tests +test262-test-sys-prop.test.js.enable.strict.mode=true + +# file containing test262 tests to be excluded +# test262-test-sys-prop.test.js.excludes.file=${test262.dir}/test/config/excludelist.xml + +# list of test262 test dirs to be excluded +test262-test-sys-prop.test.js.exclude.dir=\ + ${test262.suite.dir}/intl402/ + +# test262 test frameworks +test262-test-sys-prop.test.js.framework=\ + -timezone=PST \ + ${test.script.dir}/test262.js \ + ${test262.dir}/test/harness/framework.js \ + ${test262.dir}/test/harness/sta.js + +run.test.classpath=\ + ${file.reference.testng.jar}:\ + ${build.test.classes.dir} +src.dir=src +test.src.dir=test/src + +# -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintNMethods +# add '-Dtest.js.outofprocess' to run each test in a new sub-process +run.test.jvmargs=-server -Xmx3G -XX:-TieredCompilation -esa -ea -Dnashorn.debug=true -Dfile.encoding=UTF-8 +#-XX:+HeapDumpOnOutOfMemoryError -XX:-UseCompressedKlassPointers -XX:+PrintHeapAtGC -XX:ClassMetaspaceSize=300M +run.test.jvmargs.octane=-Xms2G -Xmx2G ${run.test.jvmargs} + +run.test.jvmsecurityargs=-Xverify:all -Djava.security.manager -Djava.security.policy=${basedir}/build/nashorn.policy + +# path of rhino.jar for benchmarks +rhino.jar= + +v8.shell=d8 + +#path to rhino jar file +octaneperf-sys-prop.rhino.jar=${rhino.jar} + +#timeout for performance tests in minutes +octaneperf-sys-prop.timeout.value=10 diff --git a/samples/counters.js b/samples/counters.js new file mode 100644 index 00000000..eb55d287 --- /dev/null +++ b/samples/counters.js @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2010, 2012, 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 file can be run along with any script you want to run + * to print aggregate stat counters from nashorn. + * + * Usage: jjs <your-file.js> counters.js + */ + +Debug.dumpCounters(); diff --git a/samples/letter.js b/samples/letter.js new file mode 100644 index 00000000..d45bd086 --- /dev/null +++ b/samples/letter.js @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2010, 2012, 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. + */ + +/** + * Demonstrates "heredoc" feature with "scripting" mode. + * + * Usage: jjs -scripting letter.js -- <sender> <recipient> + */ + +# This is shell-style line comment +var obj = { sender: $ARG[0], recipient: $ARG[1] }; + +// JavaScript style line comment is ok too. +print(<<EOF); +Dear ${obj.recipient}, + +I wish you all the best. + +Regards, +${obj.sender} +EOF diff --git a/samples/parser.js b/samples/parser.js new file mode 100644 index 00000000..a738c03b --- /dev/null +++ b/samples/parser.js @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2010, 2012, 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 parser API. + */ + +load("nashorn:parser.js"); +try { + var json = parse("print('hello')"); + print(JSON.stringify(json)); +} catch (e) { + print(e); +} diff --git a/samples/shell.js b/samples/shell.js new file mode 100644 index 00000000..380e6d70 --- /dev/null +++ b/samples/shell.js @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2010, 2012, 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 is a simple shell tool in JavaScript. + * + * Runs any operating system command using Java "exec". When "eval" command is + * used, evaluates argument(s) as JavaScript code. + */ + +var imports = new JavaImporter(java.io, java.lang, java.util); + +function prompt() { + java.lang.System.out.print(">"); +} + +with (imports) { + var reader = new BufferedReader(new InputStreamReader(System["in"])); + var line = null; + prompt(); + while ((line = reader.readLine()) != null) { + if (line != "") { + var args = line.split(" "); + try { + if (args[0] == "eval") { + var code = line.substring("eval".length); + var res = eval(code); + if (res != undefined) { + print(res); + } + } else { + var argList = new ArrayList(); + for (i in args) { argList.add(args[i]); } + var procBuilder = new ProcessBuilder(argList); + procBuilder.redirectErrorStream(); + var proc = procBuilder.start(); + var out = new BufferedReader(new InputStreamReader(proc.getInputStream())); + var line = null; + while ((line = out.readLine()) != null) { + System.out.println(line); + } + proc.waitFor(); + } + } catch (e) { + print(e); + } + } + prompt(); + } +} diff --git a/samples/test.js b/samples/test.js new file mode 100644 index 00000000..e1d30b0a --- /dev/null +++ b/samples/test.js @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2010, 2012, 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("Hello World"); diff --git a/samples/uniq.js b/samples/uniq.js new file mode 100644 index 00000000..157c4f59 --- /dev/null +++ b/samples/uniq.js @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2010, 2012, 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. + */ + +/** + * Prints unique lines from a given file. + */ + +if (arguments.length != 1) { + print("Usage: jjs uniq.js -- <file>"); + java.lang.System.exit(1); +} + +var imports = new JavaImporter(java.io); + +var uniqueLines = {}; +with (imports) { + var reader = new BufferedReader(new FileReader(arguments[0])); + while ((line = reader.readLine()) != null) { + // using a JS object as a map... + uniqueLines[line] = true; + } +} + +// now print the collected lines +for (i in uniqueLines) { + print(i); +} diff --git a/src/META-INF/MANIFEST.MF b/src/META-INF/MANIFEST.MF new file mode 100644 index 00000000..b61190e5 --- /dev/null +++ b/src/META-INF/MANIFEST.MF @@ -0,0 +1,5 @@ +Manifest-Version: 1.0
+Main-Class: jdk.nashorn.tools.Shell
+
+Name: jdk/nashorn/
+Implementation-Vendor: Oracle Corporation
diff --git a/src/META-INF/services/javax.script.ScriptEngineFactory b/src/META-INF/services/javax.script.ScriptEngineFactory new file mode 100644 index 00000000..ec7da013 --- /dev/null +++ b/src/META-INF/services/javax.script.ScriptEngineFactory @@ -0,0 +1,25 @@ +# +# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# +jdk.nashorn.api.scripting.NashornScriptEngineFactory diff --git a/src/jdk/nashorn/api/scripting/NashornException.java b/src/jdk/nashorn/api/scripting/NashornException.java new file mode 100644 index 00000000..f1a42648 --- /dev/null +++ b/src/jdk/nashorn/api/scripting/NashornException.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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; + +/** + * This is base exception for all Nashorn exceptions. These originate from user's + * ECMAScript code. Example: script parse errors, exceptions thrown from scripts. + * Note that ScriptEngine methods like "eval", "invokeMethod", "invokeFunction" + * will wrap this as ScriptException and throw it. But, there are cases where user + * may need to access this exception (or implementation defined subtype of this). + * For example, if java interface is implemented by a 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. + */ +@SuppressWarnings("serial") +public class NashornException extends RuntimeException { + // script file name + private String fileName; + // script line number + private int line; + // script column number + private int column; + + /** + * Constructor + * + * @param msg exception message + */ + protected NashornException(final String msg) { + super(msg); + } + + /** + * Constructor + * @param msg exception message + * @param cause exception cause + */ + protected NashornException(final String msg, final Throwable cause) { + super(msg, cause); + } + + /** + * Constructor + * + * @param cause exception cause + */ + protected NashornException(final Throwable cause) { + super(cause); + } + + /** + * Get the source file name for this {@code NashornException} + * @return the file name + */ + public final String getFileName() { + return fileName; + } + + /** + * Set the source file name for this {@code NashornException} + * @param fileName file name + */ + protected final void setFileName(final String fileName) { + this.fileName = fileName; + } + + /** + * Get the line number for this {@code NashornException} + * @return the line number + */ + public final int getLineNumber() { + return line; + } + + /** + * Set the line number for this {@code NashornException} + * @param line line number + */ + protected final void setLineNumber(final int line) { + this.line = line; + } + + /** + * Get the column for this {@code NashornException} + * @return the column + */ + public final int getColumnNumber() { + return column; + } + + /** + * Set the column number for this {@code NashornException} + * @param column the column + */ + public final void setColumnNumber(final int column) { + this.column = column; + } +} diff --git a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java new file mode 100644 index 00000000..3fde40aa --- /dev/null +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java @@ -0,0 +1,521 @@ +/* + * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 static jdk.nashorn.internal.runtime.ECMAErrors.referenceError; +import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; +import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; +import static jdk.nashorn.internal.runtime.linker.Lookup.MH; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.lang.invoke.MethodHandle; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import javax.script.AbstractScriptEngine; +import javax.script.Bindings; +import javax.script.Compilable; +import javax.script.CompiledScript; +import javax.script.Invocable; +import javax.script.ScriptContext; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineFactory; +import javax.script.ScriptException; +import javax.script.SimpleBindings; +import jdk.nashorn.internal.runtime.Context; +import jdk.nashorn.internal.runtime.ErrorManager; +import jdk.nashorn.internal.runtime.GlobalObject; +import jdk.nashorn.internal.runtime.Property; +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.linker.JavaAdapterFactory; +import jdk.nashorn.internal.runtime.options.Options; + +/** + * JSR-223 compliant script engine for Nashorn. Instances are not created directly, but rather returned through + * {@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 + */ + +public final class NashornScriptEngine extends AbstractScriptEngine implements Compilable, Invocable { + + private final ScriptEngineFactory factory; + private final Context nashornContext; + private final ScriptObject global; + + // default options passed to Nashorn Options object + private static final String[] DEFAULT_OPTIONS = new String[] { "-scripting", "-af", "-doe" }; + + NashornScriptEngine(final NashornScriptEngineFactory factory) { + this(factory, DEFAULT_OPTIONS); + } + + @SuppressWarnings("LeakingThisInConstructor") + NashornScriptEngine(final NashornScriptEngineFactory factory, final String[] args) { + this.factory = factory; + final Options options = new Options("nashorn"); + options.process(args); + + // throw ParseException on first error from script + final ErrorManager errors = new Context.ThrowErrorManager(); + // create new Nashorn Context and get global object + this.nashornContext = AccessController.doPrivileged(new PrivilegedAction<Context>() { + @Override + public Context run() { + |