# HG changeset patch # User Tom Rodriguez # Date 1389047423 28800 # Node ID 1ceb90be7bac1de777b58a96038f84063793b574 # Parent 622af5fb8c58a9cfd359ec952831039efde7e83a# Parent fa5180b3c18e02f940516be1da3f1d3dc364deb2 Merge diff -r 622af5fb8c58 -r 1ceb90be7bac .hgignore --- a/.hgignore Fri Jan 03 16:38:57 2014 -0800 +++ b/.hgignore Mon Jan 06 14:30:23 2014 -0800 @@ -85,3 +85,5 @@ agent/build/* agent/make/filelist agent/make/sa17.tar.gz +graal/com.oracle.truffle.ruby.test/specs/mspec +graal/com.oracle.truffle.ruby.test/specs/rubyspec diff -r 622af5fb8c58 -r 1ceb90be7bac LICENSE.EPL --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LICENSE.EPL Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,242 @@ +Some parts of this software are marked as being licensed to you under the terms +of the Eclipse Public License version 1.0, as follows. + + THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE + PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION + OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + + 1. DEFINITIONS + + "Contribution" means: + + a) in the case of the initial Contributor, the initial code and + documentation distributed under this Agreement, and + + b) in the case of each subsequent Contributor: + + i) changes to the Program, and + + ii) additions to the Program; + where such changes and/or additions to the Program + originate from and are distributed by that particular + Contributor. A Contribution 'originates' from a + Contributor if it was added to the Program by such + Contributor itself or anyone acting on such + Contributor's behalf. Contributions do not include + additions to the Program which: (i) are separate modules + of software distributed in conjunction with the Program + under their own license agreement, and (ii) are not + derivative works of the Program. + + "Contributor" means any person or entity that distributes the Program. + + "Licensed Patents" mean patent claims licensable by a Contributor + which are necessarily infringed by the use or sale of its + Contribution alone or when combined with the Program. + + "Program" means the Contributions distributed in accordance with + this Agreement. + + "Recipient" means anyone who receives the Program under this + Agreement, including all Contributors. + + 2. GRANT OF RIGHTS + + a) Subject to the terms of this Agreement, each Contributor + hereby grants Recipient a non-exclusive, worldwide, + royalty-free copyright license to reproduce, prepare + derivative works of, publicly display, publicly perform, + distribute and sublicense the Contribution of such + Contributor, if any, and such derivative works, in source + code and object code form. + + b) Subject to the terms of this Agreement, each Contributor + hereby grants Recipient a non-exclusive, worldwide, + royalty-free patent license under Licensed Patents to make, + use, sell, offer to sell, import and otherwise transfer the + Contribution of such Contributor, if any, in source code and + object code form. This patent license shall apply to the + combination of the Contribution and the Program if, at the + time the Contribution is added by the Contributor, such + addition of the Contribution causes such combination to be + covered by the Licensed Patents. The patent license shall not + apply to any other combinations which include the + Contribution. No hardware per se is licensed hereunder. + + c) Recipient understands that although each Contributor grants + the licenses to its Contributions set forth herein, no + assurances are provided by any Contributor that the Program + does not infringe the patent or other intellectual property + rights of any other entity. Each Contributor disclaims any + liability to Recipient for claims brought by any other entity + based on infringement of intellectual property rights or + otherwise. As a condition to exercising the rights and + licenses granted hereunder, each Recipient hereby assumes + sole responsibility to secure any other intellectual property + rights needed, if any. For example, if a third party patent + license is required to allow Recipient to distribute the + Program, it is Recipient's responsibility to acquire that + license before distributing the Program. + + d) Each Contributor represents that to its knowledge it has + sufficient copyright rights in its Contribution, if any, to + grant the copyright license set forth in this Agreement. + + 3. REQUIREMENTS + + A Contributor may choose to distribute the Program in object code + form under its own license agreement, provided that: + + a) it complies with the terms and conditions of this Agreement; and + + b) its license agreement: + + i) effectively disclaims on behalf of all Contributors all + warranties and conditions, express and implied, including + warranties or conditions of title and non-infringement, + and implied warranties or conditions of merchantability + and fitness for a particular purpose; + + ii) effectively excludes on behalf of all Contributors all + liability for damages, including direct, indirect, + special, incidental and consequential damages, such as + lost profits; + + iii) states that any provisions which differ from this + Agreement are offered by that Contributor alone and not + by any other party; and + + iv) states that source code for the Program is available + from such Contributor, and informs licensees how to + obtain it in a reasonable manner on or through a medium + customarily used for software exchange. + + When the Program is made available in source code form: + + a) it must be made available under this Agreement; and + + b) a copy of this Agreement must be included with each copy of + the Program. + + Contributors may not remove or alter any copyright notices contained + within the Program. + + Each Contributor must identify itself as the originator of its + Contribution, if any, in a manner that reasonably allows subsequent + Recipients to identify the originator of the Contribution. + + 4. COMMERCIAL DISTRIBUTION + + Commercial distributors of software may accept certain + responsibilities with respect to end users, business partners and + the like. While this license is intended to facilitate the + commercial use of the Program, the Contributor who includes the + Program in a commercial product offering should do so in a manner + which does not create potential liability for other Contributors. + Therefore, if a Contributor includes the Program in a commercial + product offering, such Contributor ("Commercial Contributor") hereby + agrees to defend and indemnify every other Contributor ("Indemnified + Contributor") against any losses, damages and costs (collectively + "Losses") arising from claims, lawsuits and other legal actions + brought by a third party against the Indemnified Contributor to the + extent caused by the acts or omissions of such Commercial + Contributor in connection with its distribution of the Program in a + commercial product offering. The obligations in this section do not + apply to any claims or Losses relating to any actual or alleged + intellectual property infringement. In order to qualify, an + Indemnified Contributor must: a) promptly notify the Commercial + Contributor in writing of such claim, and b) allow the Commercial + Contributor to control, and cooperate with the Commercial + Contributor in, the defense and any related settlement negotiations. + The Indemnified Contributor may participate in any such claim at its + own expense. + + For example, a Contributor might include the Program in a commercial + product offering, Product X. That Contributor is then a Commercial + Contributor. If that Commercial Contributor then makes performance + claims, or offers warranties related to Product X, those performance + claims and warranties are such Commercial Contributor's + responsibility alone. Under this section, the Commercial Contributor + would have to defend claims against the other Contributors related + to those performance claims and warranties, and if a court requires + any other Contributor to pay any damages as a result, the Commercial + Contributor must pay those damages. + + 5. NO WARRANTY + + EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS + PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF + ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, + ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient + is solely responsible for determining the appropriateness of using + and distributing the Program and assumes all risks associated with + its exercise of rights under this Agreement , including but not + limited to the risks and costs of program errors, compliance with + applicable laws, damage to or loss of data, programs or equipment, + and unavailability or interruption of operations. + + 6. DISCLAIMER OF LIABILITY + + EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT + NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS + GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGES. + + 7. GENERAL + + If any provision of this Agreement is invalid or unenforceable under + applicable law, it shall not affect the validity or enforceability + of the remainder of the terms of this Agreement, and without further + action by the parties hereto, such provision shall be reformed to + the minimum extent necessary to make such provision valid and + enforceable. + + If Recipient institutes patent litigation against any entity + (including a cross-claim or counterclaim in a lawsuit) alleging that + the Program itself (excluding combinations of the Program with other + software or hardware) infringes such Recipient's patent(s), then + such Recipient's rights granted under Section 2(b) shall terminate + as of the date such litigation is filed. + + All Recipient's rights under this Agreement shall terminate if it + fails to comply with any of the material terms or conditions of this + Agreement and does not cure such failure in a reasonable period of + time after becoming aware of such noncompliance. If all Recipient's + rights under this Agreement terminate, Recipient agrees to cease use + and distribution of the Program as soon as reasonably practicable. + However, Recipient's obligations under this Agreement and any + licenses granted by Recipient relating to the Program shall continue + and survive. + + Everyone is permitted to copy and distribute copies of this + Agreement, but in order to avoid inconsistency the Agreement is + copyrighted and may only be modified in the following manner. The + Agreement Steward reserves the right to publish new versions + (including revisions) of this Agreement from time to time. No one + other than the Agreement Steward has the right to modify this + Agreement. The Eclipse Foundation is the initial Agreement Steward. + The Eclipse Foundation may assign the responsibility to serve as the + Agreement Steward to a suitable separate entity. Each new version of + the Agreement will be given a distinguishing version number. The + Program (including Contributions) may always be distributed subject + to the version of the Agreement under which it was received. In + addition, after a new version of the Agreement is published, + Contributor may elect to distribute the Program (including its + Contributions) under the new version. Except as expressly stated in + Sections 2(a) and 2(b) above, Recipient receives no rights or + licenses to the intellectual property of any Contributor under this + Agreement, whether expressly, by implication, estoppel or otherwise. + All rights in the Program not expressly granted under this Agreement + are reserved. + + This Agreement is governed by the laws of the State of New York and + the intellectual property laws of the United States of America. No + party to this Agreement will bring a legal action under this + Agreement more than one year after the cause of action arose. Each + party waives its rights to a jury trial in any resulting litigation. diff -r 622af5fb8c58 -r 1ceb90be7bac LICENSE.LGPL --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LICENSE.LGPL Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,505 @@ +Some parts of this software are marked as being licensed to you under the terms +of the GNU Lesser General Public License version 2.1, as follows. + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 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. + + [This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your + freedom to share and change it. By contrast, the GNU General Public + Licenses are intended to guarantee your freedom to share and change + free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some + specially designated software packages--typically libraries--of the + Free Software Foundation and other authors who decide to use it. You + can use it too, but we suggest you first think carefully about whether + this license or the ordinary General Public License is the better + strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, + 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 and use pieces of + it in new free programs; and that you are informed that you can do + these things. + + To protect your rights, we need to make restrictions that forbid + distributors to deny you these rights or to ask you to surrender these + rights. These restrictions translate to certain responsibilities for + you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis + or for a fee, you must give the recipients all the rights that we gave + you. You must make sure that they, too, receive or can get the source + code. If you link other code with the library, you must provide + complete object files to the recipients, so that they can relink them + with the library after making changes to the library and recompiling + it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the + library, and (2) we offer you this license, which gives you legal + permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that + there is no warranty for the free library. Also, if the library is + modified by someone else and passed on, the recipients should know + that what they have is not the original version, so that the original + author's reputation will not be affected by problems that might be + introduced by others. + + Finally, software patents pose a constant threat to the existence of + any free program. We wish to make sure that a company cannot + effectively restrict the users of a free program by obtaining a + restrictive license from a patent holder. Therefore, we insist that + any patent license obtained for a version of the library must be + consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the + ordinary GNU General Public License. This license, the GNU Lesser + General Public License, applies to certain designated libraries, and + is quite different from the ordinary General Public License. We use + this license for certain libraries in order to permit linking those + libraries into non-free programs. + + When a program is linked with a library, whether statically or using + a shared library, the combination of the two is legally speaking a + combined work, a derivative of the original library. The ordinary + General Public License therefore permits such linking only if the + entire combination fits its criteria of freedom. The Lesser General + Public License permits more lax criteria for linking other code with + the library. + + We call this license the "Lesser" General Public License because it + does Less to protect the user's freedom than the ordinary General + Public License. It also provides other free software developers Less + of an advantage over competing non-free programs. These disadvantages + are the reason we use the ordinary General Public License for many + libraries. However, the Lesser license provides advantages in certain + special circumstances. + + For example, on rare occasions, there may be a special need to + encourage the widest possible use of a certain library, so that it becomes + a de-facto standard. To achieve this, non-free programs must be + allowed to use the library. A more frequent case is that a free + library does the same job as widely used non-free libraries. In this + case, there is little to gain by limiting the free library to free + software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free + programs enables a greater number of people to use a large body of + free software. For example, permission to use the GNU C Library in + non-free programs enables many more people to use the whole GNU + operating system, as well as its variant, the GNU/Linux operating + system. + + Although the Lesser General Public License is Less protective of the + users' freedom, it does ensure that the user of a program that is + linked with the Library has the freedom and the wherewithal to run + that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and + modification follow. Pay close attention to the difference between a + "work based on the library" and a "work that uses the library". The + former contains code derived from the library, whereas the latter must + be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other + program which contains a notice placed by the copyright holder or + other authorized party saying it may be distributed under the terms of + this Lesser General Public License (also called "this License"). + Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data + prepared so as to be conveniently linked with application programs + (which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work + which has been distributed under these terms. A "work based on the + Library" means either the Library or any derivative work under + copyright law: that is to say, a work containing the Library or a + portion of it, either verbatim or with modifications and/or translated + straightforwardly into another language. (Hereinafter, translation is + included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for + making modifications to it. For a library, 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 library. + + Activities other than copying, distribution and modification are not + covered by this License; they are outside its scope. The act of + running a program using the Library is not restricted, and output from + such a program is covered only if its contents constitute a work based + on the Library (independent of the use of the Library in a tool for + writing it). Whether that is true depends on what the Library does + and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's + complete 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 distribute a copy of this License along with the + Library. + + 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 Library or any portion + of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + + These requirements apply to the modified work as a whole. If + identifiable sections of that work are not derived from the Library, + 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 Library, 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 Library. + + In addition, mere aggregation of another work not based on the Library + with the Library (or with a work based on the Library) on a volume of + a storage or distribution medium does not bring the other work under + the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public + License instead of this License to a given copy of the Library. To do + this, you must alter all the notices that refer to this License, so + that they refer to the ordinary GNU General Public License, version 2, + instead of to this License. (If a newer version than version 2 of the + ordinary GNU General Public License has appeared, then you can specify + that version instead if you wish.) Do not make any other change in + these notices. + + Once this change is made in a given copy, it is irreversible for + that copy, so the ordinary GNU General Public License applies to all + subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of + the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or + derivative of it, under Section 2) in object code or executable form + under the terms of Sections 1 and 2 above provided that you 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. + + If distribution of 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 satisfies the requirement to + distribute the source code, even though third parties are not + compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the + Library, but is designed to work with the Library by being compiled or + linked with it, is called a "work that uses the Library". Such a + work, in isolation, is not a derivative work of the Library, and + therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library + creates an executable that is a derivative of the Library (because it + contains portions of the Library), rather than a "work that uses the + library". The executable is therefore covered by this License. + Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file + that is part of the Library, the object code for the work may be a + derivative work of the Library even though the source code is not. + Whether this is true is especially significant if the work can be + linked without the Library, or if the work is itself a library. The + threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data + structure layouts and accessors, and small macros and small inline + functions (ten lines or less in length), then the use of the object + file is unrestricted, regardless of whether it is legally a derivative + work. (Executables containing this object code plus portions of the + Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may + distribute the object code for the work under the terms of Section 6. + Any executables containing that work also fall under Section 6, + whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or + link a "work that uses the Library" with the Library to produce a + work containing portions of the Library, and distribute that work + under terms of your choice, provided that the terms permit + modification of the work for the customer's own use and reverse + engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the + Library is used in it and that the Library and its use are covered by + this License. You must supply a copy of this License. If the work + during execution displays copyright notices, you must include the + copyright notice for the Library among them, as well as a reference + directing the user to the copy of this License. Also, you must do one + of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the + Library" must include any data and utility programs needed for + reproducing the executable from it. However, as a special exception, + the materials to be 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. + + It may happen that this requirement contradicts the license + restrictions of other proprietary libraries that do not normally + accompany the operating system. Such a contradiction means you cannot + use both them and the Library together in an executable that you + distribute. + + 7. You may place library facilities that are a work based on the + Library side-by-side in a single library together with other library + facilities not covered by this License, and distribute such a combined + library, provided that the separate distribution of the work based on + the Library and of the other library facilities is otherwise + permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute + the Library except as expressly provided under this License. Any + attempt otherwise to copy, modify, sublicense, link with, or + distribute the Library 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. + + 9. 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 Library or its derivative works. These actions are + prohibited by law if you do not accept this License. Therefore, by + modifying or distributing the Library (or any work based on the + Library), you indicate your acceptance of this License to do so, and + all its terms and conditions for copying, distributing or modifying + the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the + Library), the recipient automatically receives a license from the + original licensor to copy, distribute, link with or modify the Library + 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 with + this License. + + 11. 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 Library at all. For example, if a patent + license would not permit royalty-free redistribution of the Library 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 Library. + + 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. + + 12. If the distribution and/or use of the Library is restricted in + certain countries either by patents or by copyrighted interfaces, the + original copyright holder who places the Library 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. + + 13. The Free Software Foundation may publish revised and/or new + versions of the Lesser 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 Library + 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 Library does not specify a + license version number, you may choose any version ever published by + the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free + programs whose distribution conditions are incompatible with these, + 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 + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO + WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. + EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR + OTHER PARTIES PROVIDE THE LIBRARY "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 + LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME + THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. 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 LIBRARY 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 + LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries + + If you develop a new library, and you want it to be of the greatest + possible use to the public, we recommend making it free software that + everyone can redistribute and change. You can do so by permitting + redistribution under these terms (or, alternatively, under the terms of the + ordinary General Public License). + + To apply these terms, attach the following notices to the library. 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. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; 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. + + You should also get your employer (if you work as a programmer) or your + school, if any, to sign a "copyright disclaimer" for the library, if + necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + + That's all there is to it! diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java Mon Jan 06 14:30:23 2014 -0800 @@ -32,6 +32,7 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -259,7 +260,7 @@ CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); PhaseContext context = new PhaseContext(getProviders(), null); - new LoweringPhase(canonicalizer).apply(graph, context); + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); new ConditionalEliminationPhase(getMetaAccess()).apply(graph); canonicalizer.apply(graph, context); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java Mon Jan 06 14:30:23 2014 -0800 @@ -30,6 +30,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -59,7 +60,7 @@ StructuredGraph graph = parse(snippet); PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false)); - new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, context); + new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new FloatingReadPhase().apply(graph); ReturnNode returnNode = null; diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java Mon Jan 06 14:30:23 2014 -0800 @@ -29,6 +29,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -95,7 +96,7 @@ new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context); new CanonicalizerPhase(true).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); - new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, context); + new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new ValueAnchorCleanupPhase().apply(graph); new LockEliminationPhase().apply(graph); return graph; diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java Mon Jan 06 14:30:23 2014 -0800 @@ -37,6 +37,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.options.*; import com.oracle.graal.options.OptionValue.OverrideScope; @@ -592,7 +593,7 @@ if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { new InliningPhase(canonicalizer).apply(graph, context); } - new LoweringPhase(canonicalizer).apply(graph, context); + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { for (Node node : graph.getNodes()) { if (node instanceof StateSplit) { @@ -611,8 +612,8 @@ MidTierContext midContext = new MidTierContext(getProviders(), assumptions, getCodeCache().getTarget(), OptimisticOptimizations.ALL, graph.method().getProfilingInfo()); new GuardLoweringPhase().apply(graph, midContext); - new LoweringPhase(canonicalizer).apply(graph, midContext); - new LoweringPhase(canonicalizer).apply(graph, midContext); + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); SchedulePhase schedule = new SchedulePhase(schedulingStrategy, memsched); schedule.apply(graph); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java Mon Jan 06 14:30:23 2014 -0800 @@ -31,6 +31,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -92,7 +93,7 @@ StructuredGraph graph = parse(snippet); PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false)); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true); - new LoweringPhase(canonicalizer).apply(graph, context); + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); new PushThroughPiPhase().apply(graph); canonicalizer.apply(graph, context); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java --- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java Mon Jan 06 14:30:23 2014 -0800 @@ -30,6 +30,7 @@ import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -83,7 +84,7 @@ // structure changes significantly StructuredGraph graph = parse(snippet); PhaseContext context = new PhaseContext(getProviders(), new Assumptions(false)); - new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, context); + new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new FloatingReadPhase().apply(graph); new OptimizeGuardAnchors().apply(graph); new ReadEliminationPhase().apply(graph); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Mon Jan 06 14:30:23 2014 -0800 @@ -486,9 +486,17 @@ } } } - if (block.getSuccessorCount() >= 1 && !hasBlockEnd(block)) { + + if (!hasBlockEnd(block)) { NodeClassIterable successors = block.getEndNode().successors(); - assert successors.isNotEmpty() : "should have at least one successor : " + block.getEndNode(); + assert successors.count() == block.getSuccessorCount(); + if (block.getSuccessorCount() != 1) { + /* + * If we have more than one successor, we cannot just use the first one. Since + * successors are unordered, this would be a random choice. + */ + throw new GraalInternalError("Block without BlockEndOp: " + block.getEndNode()); + } emitJump(getLIRBlock((FixedNode) successors.first())); } @@ -731,6 +739,10 @@ if (isLegal(result)) { setResult(x.asNode(), emitMove(result)); } + + if (x instanceof InvokeWithExceptionNode) { + emitJump(getLIRBlock(((InvokeWithExceptionNode) x).next())); + } } protected abstract void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java Mon Jan 06 14:30:23 2014 -0800 @@ -28,6 +28,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.loop.phases.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; @@ -101,6 +102,6 @@ appendPhase(canonicalizer); } - appendPhase(new LoweringPhase(canonicalizer)); + appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER)); } } diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java Mon Jan 06 14:30:23 2014 -0800 @@ -24,6 +24,7 @@ import static com.oracle.graal.phases.GraalOptions.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -33,7 +34,7 @@ public LowTier() { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!ImmutableCode.getValue()); - appendPhase(new LoweringPhase(canonicalizer)); + appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER)); appendPhase(new RemoveValueProxyPhase()); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java Mon Jan 06 14:30:23 2014 -0800 @@ -25,6 +25,7 @@ import static com.oracle.graal.phases.GraalOptions.*; import com.oracle.graal.loop.phases.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -85,7 +86,7 @@ appendPhase(new GuardLoweringPhase()); - appendPhase(new LoweringPhase(canonicalizer)); + appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER)); appendPhase(new FrameStateAssignmentPhase()); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java Mon Jan 06 14:30:23 2014 -0800 @@ -25,6 +25,7 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.asm.NumUtil.*; import static com.oracle.graal.hotspot.bridge.Marks.*; +import static com.oracle.graal.phases.GraalOptions.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -49,7 +50,7 @@ public AMD64HotSpotSafepointOp(LIRFrameState state, HotSpotVMConfig config, LIRGeneratorTool tool) { this.state = state; this.config = config; - if (isPollingPageFar(config)) { + if (isPollingPageFar(config) || ImmutableCode.getValue()) { temp = tool.newVariable(tool.target().wordKind); } else { // Don't waste a register if it's unneeded @@ -72,7 +73,20 @@ } public static void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler asm, HotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) { - if (isPollingPageFar(config)) { + if (ImmutableCode.getValue()) { + Kind hostWordKind = HotSpotGraalRuntime.getHostWordKind(); + int alignment = hostWordKind.getBitCount() / Byte.SIZE; + Constant pollingPageAddress = Constant.forIntegerKind(hostWordKind, config.safepointPollingAddress, null); + // This move will be patched to load the safepoint page from a data segment + // co-located with the immutable code. + asm.movq(scratch, (AMD64Address) crb.recordDataReferenceInCode(pollingPageAddress, alignment, false)); + final int pos = asm.codeBuffer.position(); + crb.recordMark(atReturn ? MARK_POLL_RETURN_FAR : MARK_POLL_FAR); + if (state != null) { + crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); + } + asm.testl(rax, new AMD64Address(scratch)); + } else if (isPollingPageFar(config)) { asm.movq(scratch, config.safepointPollingAddress); crb.recordMark(atReturn ? MARK_POLL_RETURN_FAR : MARK_POLL_FAR); final int pos = asm.codeBuffer.position(); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMonitorValueTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/HotSpotMonitorValueTest.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.test; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import java.util.*; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.CompilationResult.Call; +import com.oracle.graal.api.code.CompilationResult.Infopoint; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.meta.*; + +public class HotSpotMonitorValueTest extends GraalCompilerTest { + + @Override + protected InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) { + for (Infopoint i : compResult.getInfopoints()) { + if (i instanceof Call) { + Call call = (Call) i; + if (call.target instanceof ResolvedJavaMethod) { + ResolvedJavaMethod target = (ResolvedJavaMethod) call.target; + if (target.equals(lookupObjectWait())) { + BytecodeFrame frame = call.debugInfo.frame(); + BytecodeFrame caller = frame.caller(); + assertNotNull(caller); + assertNull(caller.caller()); + assertEquals(2, frame.numLocks); + assertEquals(2, caller.numLocks); + HotSpotMonitorValue lock1 = (HotSpotMonitorValue) frame.getLockValue(0); + HotSpotMonitorValue lock2 = (HotSpotMonitorValue) frame.getLockValue(1); + HotSpotMonitorValue lock3 = (HotSpotMonitorValue) caller.getLockValue(0); + HotSpotMonitorValue lock4 = (HotSpotMonitorValue) caller.getLockValue(1); + + List locks = Arrays.asList(lock1, lock2, lock3, lock4); + for (HotSpotMonitorValue lock : locks) { + for (HotSpotMonitorValue other : locks) { + if (other != lock) { + // Every lock must have a different stack slot + assertThat(lock.getSlot(), not(other.getSlot())); + } + } + } + assertEquals(lock3.getOwner(), lock4.getOwner()); + assertThat(lock1.getOwner(), not(lock2.getOwner())); + return super.addMethod(method, compResult); + } + } + } + } + throw new AssertionError("Could not find debug info for call to Object.wait(long)"); + } + + private ResolvedJavaMethod lookupObjectWait() { + try { + return getMetaAccess().lookupJavaMethod(Object.class.getDeclaredMethod("wait", long.class)); + } catch (Exception e) { + throw new GraalInternalError("Could not find Object.wait(long): %s", e); + } + } + + @Test + public void test() { + test("testSnippet", "a", "b"); + } + + private static void locks2(Object a, Object b) throws InterruptedException { + synchronized (a) { + synchronized (b) { + a.wait(5); + } + } + } + + public static void testSnippet(Object a, Object b) throws InterruptedException { + synchronized (a) { + synchronized (a) { + locks2(a, b); + } + } + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierAdditionTest.java Mon Jan 06 14:30:23 2014 -0800 @@ -41,6 +41,7 @@ import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; @@ -249,9 +250,9 @@ HighTierContext highContext = new HighTierContext(getProviders(), new Assumptions(false), null, getDefaultPhasePlan(), OptimisticOptimizations.ALL); MidTierContext midContext = new MidTierContext(getProviders(), new Assumptions(false), getCodeCache().getTarget(), OptimisticOptimizations.ALL, graph.method().getProfilingInfo()); new InliningPhase(new InliningPhase.InlineEverythingPolicy(), new CanonicalizerPhase(true)).apply(graph, highContext); - new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, highContext); + new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highContext); new GuardLoweringPhase().apply(graph, midContext); - new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, midContext); + new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); new WriteBarrierAdditionPhase().apply(graph); Debug.dump(graph, "After Write Barrier Addition"); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/WriteBarrierVerificationTest.java Mon Jan 06 14:30:23 2014 -0800 @@ -37,6 +37,7 @@ import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.graph.*; @@ -617,10 +618,10 @@ MidTierContext midTierContext = new MidTierContext(getProviders(), new Assumptions(false), getCodeCache().getTarget(), OptimisticOptimizations.ALL, graph.method().getProfilingInfo()); - new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext); + new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext); new GuardLoweringPhase().apply(graph, midTierContext); new LoopSafepointInsertionPhase().apply(graph); - new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, highTierContext); + new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, highTierContext); new WriteBarrierAdditionPhase().apply(graph); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugInfoBuilder.java Mon Jan 06 14:30:23 2014 -0800 @@ -51,7 +51,7 @@ protected Value computeLockValue(FrameState state, int i) { int lockDepth = i; if (state.outerFrameState() != null) { - lockDepth = state.outerFrameState().nestedLockDepth(); + lockDepth += state.outerFrameState().nestedLockDepth(); } StackSlot slot = lockStack.makeLockSlot(lockDepth); ValueNode lock = state.lockAt(i); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotLoweringProvider.java Mon Jan 06 14:30:23 2014 -0800 @@ -246,7 +246,7 @@ if (checkcastNode != null) { checkcastNode.lower(tool); } else if (checkcastDynamicNode != null) { - checkcastDynamicSnippets.lower(checkcastDynamicNode); + checkcastDynamicSnippets.lower(checkcastDynamicNode, tool); } } else if (n instanceof UnsafeLoadNode) { UnsafeLoadNode load = (UnsafeLoadNode) n; @@ -281,12 +281,14 @@ write.setStateAfter(store.stateAfter()); graph.replaceFixedWithFixed(store, write); } else if (n instanceof LoadHubNode) { - LoadHubNode loadHub = (LoadHubNode) n; - assert loadHub.kind() == wordKind; - ValueNode object = loadHub.object(); - GuardingNode guard = loadHub.getGuard(); - FloatingReadNode hub = createReadHub(graph, wordKind, object, guard); - graph.replaceFloating(loadHub, hub); + if (graph.getGuardsStage().ordinal() == StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal()) { + LoadHubNode loadHub = (LoadHubNode) n; + assert loadHub.kind() == wordKind; + ValueNode object = loadHub.object(); + GuardingNode guard = loadHub.getGuard(); + FloatingReadNode hub = createReadHub(graph, wordKind, object, guard); + graph.replaceFloating(loadHub, hub); + } } else if (n instanceof LoadMethodNode) { LoadMethodNode loadMethodNode = (LoadMethodNode) n; ResolvedJavaMethod method = loadMethodNode.getMethod(); @@ -463,7 +465,7 @@ BenchmarkCounters.lower((DynamicCounterNode) n, registers, runtime.getConfig(), wordKind); } } else if (n instanceof CheckCastDynamicNode) { - checkcastDynamicSnippets.lower((CheckCastDynamicNode) n); + checkcastDynamicSnippets.lower((CheckCastDynamicNode) n, tool); } else if (n instanceof InstanceOfNode) { if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { instanceofSnippets.lower((InstanceOfNode) n, tool); @@ -474,44 +476,44 @@ } } else if (n instanceof NewInstanceNode) { if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { - newObjectSnippets.lower((NewInstanceNode) n, registers); + newObjectSnippets.lower((NewInstanceNode) n, registers, tool); } } else if (n instanceof NewArrayNode) { if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { - newObjectSnippets.lower((NewArrayNode) n, registers); + newObjectSnippets.lower((NewArrayNode) n, registers, tool); } } else if (n instanceof DynamicNewArrayNode) { if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { - newObjectSnippets.lower((DynamicNewArrayNode) n, registers); + newObjectSnippets.lower((DynamicNewArrayNode) n, registers, tool); } } else if (n instanceof MonitorEnterNode) { if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { - monitorSnippets.lower((MonitorEnterNode) n, registers); + monitorSnippets.lower((MonitorEnterNode) n, registers, tool); } } else if (n instanceof MonitorExitNode) { if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) { monitorSnippets.lower((MonitorExitNode) n, tool); } } else if (n instanceof G1PreWriteBarrier) { - writeBarrierSnippets.lower((G1PreWriteBarrier) n, registers); + writeBarrierSnippets.lower((G1PreWriteBarrier) n, registers, tool); } else if (n instanceof G1PostWriteBarrier) { - writeBarrierSnippets.lower((G1PostWriteBarrier) n, registers); + writeBarrierSnippets.lower((G1PostWriteBarrier) n, registers, tool); } else if (n instanceof G1ReferentFieldReadBarrier) { - writeBarrierSnippets.lower((G1ReferentFieldReadBarrier) n, registers); + writeBarrierSnippets.lower((G1ReferentFieldReadBarrier) n, registers, tool); } else if (n instanceof SerialWriteBarrier) { - writeBarrierSnippets.lower((SerialWriteBarrier) n); + writeBarrierSnippets.lower((SerialWriteBarrier) n, tool); } else if (n instanceof SerialArrayRangeWriteBarrier) { - writeBarrierSnippets.lower((SerialArrayRangeWriteBarrier) n); + writeBarrierSnippets.lower((SerialArrayRangeWriteBarrier) n, tool); } else if (n instanceof G1ArrayRangePreWriteBarrier) { - writeBarrierSnippets.lower((G1ArrayRangePreWriteBarrier) n, registers); + writeBarrierSnippets.lower((G1ArrayRangePreWriteBarrier) n, registers, tool); } else if (n instanceof G1ArrayRangePostWriteBarrier) { - writeBarrierSnippets.lower((G1ArrayRangePostWriteBarrier) n, registers); + writeBarrierSnippets.lower((G1ArrayRangePostWriteBarrier) n, registers, tool); } else if (n instanceof NewMultiArrayNode) { if (graph.getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { - newObjectSnippets.lower((NewMultiArrayNode) n); + newObjectSnippets.lower((NewMultiArrayNode) n, tool); } } else if (n instanceof LoadExceptionObjectNode) { - exceptionObjectSnippets.lower((LoadExceptionObjectNode) n, registers); + exceptionObjectSnippets.lower((LoadExceptionObjectNode) n, registers, tool); } else if (n instanceof IntegerDivNode || n instanceof IntegerRemNode || n instanceof UnsignedDivNode || n instanceof UnsignedRemNode) { // Nothing to do for division nodes. The HotSpot signal handler catches divisions by // zero and the MIN_VALUE / -1 cases. diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Mon Jan 06 14:30:23 2014 -0800 @@ -418,9 +418,15 @@ return method; } - public synchronized ResolvedJavaField createField(String fieldName, JavaType type, long offset, int flags, boolean internal) { + public synchronized ResolvedJavaField createField(String fieldName, JavaType type, long offset, int rawFlags, boolean internal) { ResolvedJavaField result = null; + /* + * Filter out flags used internally by HotSpot, to get a canonical id value. When a field is + * created from a java.lang.reflect.Field, these flags would not be available anyway. + */ + int flags = rawFlags & fieldModifiers(); + long id = offset + ((long) flags << 32); // (thomaswue) Must cache the fields, because the local load elimination only works if the @@ -436,7 +442,7 @@ fieldCache.put(id, result); } else { assert result.getName().equals(fieldName); - assert result.getModifiers() == (fieldModifiers() & flags); + assert result.getModifiers() == flags; } return result; diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java Mon Jan 06 14:30:23 2014 -0800 @@ -34,6 +34,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.*; @@ -70,11 +71,11 @@ super(providers, target); } - public void lower(CheckCastDynamicNode checkcast) { + public void lower(CheckCastDynamicNode checkcast, LoweringTool tool) { StructuredGraph graph = checkcast.graph(); ValueNode object = checkcast.object(); - Arguments args = new Arguments(dynamic, graph.getGuardsStage()); + Arguments args = new Arguments(dynamic, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", checkcast.hub()); args.add("object", object); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/InstanceOfSnippets.java Mon Jan 06 14:30:23 2014 -0800 @@ -232,23 +232,23 @@ StructuredGraph graph = instanceOf.graph(); if (hintInfo.hintHitProbability >= hintHitProbabilityThresholdForDeoptimizingSnippet()) { Hints hints = createHints(hintInfo, providers.getMetaAccess(), false, graph); - args = new Arguments(instanceofWithProfile, graph.getGuardsStage()); + args = new Arguments(instanceofWithProfile, graph.getGuardsStage(), tool.getLoweringStage()); args.add("object", object); Kind wordKind = providers.getCodeCache().getTarget().wordKind; args.addVarargs("hints", Word.class, StampFactory.forKind(wordKind), hints.hubs); args.addVarargs("hintIsPositive", boolean.class, StampFactory.forKind(Kind.Boolean), hints.isPositive); } else if (hintInfo.exact != null) { - args = new Arguments(instanceofExact, graph.getGuardsStage()); + args = new Arguments(instanceofExact, graph.getGuardsStage(), tool.getLoweringStage()); args.add("object", object); args.add("exactHub", ConstantNode.forConstant(((HotSpotResolvedObjectType) hintInfo.exact).klass(), providers.getMetaAccess(), graph)); } else if (type.isPrimaryType()) { - args = new Arguments(instanceofPrimary, graph.getGuardsStage()); + args = new Arguments(instanceofPrimary, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); args.add("object", object); args.addConst("superCheckOffset", type.superCheckOffset()); } else { Hints hints = createHints(hintInfo, providers.getMetaAccess(), false, graph); - args = new Arguments(instanceofSecondary, graph.getGuardsStage()); + args = new Arguments(instanceofSecondary, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); args.add("object", object); args.addVarargs("hints", Word.class, StampFactory.forKind(getWordKind()), hints.hubs); @@ -266,7 +266,7 @@ InstanceOfDynamicNode instanceOf = (InstanceOfDynamicNode) replacer.instanceOf; ValueNode object = instanceOf.object(); - Arguments args = new Arguments(instanceofDynamic, instanceOf.graph().getGuardsStage()); + Arguments args = new Arguments(instanceofDynamic, instanceOf.graph().getGuardsStage(), tool.getLoweringStage()); args.add("mirror", instanceOf.mirror()); args.add("object", object); args.add("trueValue", replacer.trueValue); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Mon Jan 06 14:30:23 2014 -0800 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.replacements; -import static com.oracle.graal.hotspot.meta.HotSpotHostForeignCallsProvider.*; +import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProviderImpl.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; import static com.oracle.graal.nodes.PiNode.*; import static com.oracle.graal.replacements.SnippetTemplate.*; @@ -32,9 +32,10 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; import com.oracle.graal.replacements.SnippetTemplate.Arguments; import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; @@ -68,7 +69,7 @@ super(providers, target); } - public void lower(LoadExceptionObjectNode loadExceptionObject, HotSpotRegistersProvider registers) { + public void lower(LoadExceptionObjectNode loadExceptionObject, HotSpotRegistersProvider registers, LoweringTool tool) { if (USE_C_RUNTIME) { StructuredGraph graph = loadExceptionObject.graph(); ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), true, false)); @@ -77,7 +78,7 @@ loadExceptionC.setStateAfter(loadExceptionObject.stateAfter()); graph.replaceFixedWithFixed(loadExceptionObject, loadExceptionC); } else { - Arguments args = new Arguments(loadException, loadExceptionObject.graph().getGuardsStage()); + Arguments args = new Arguments(loadException, loadExceptionObject.graph().getGuardsStage(), tool.getLoweringStage()); args.addConst("threadRegister", registers.getThreadRegister()); template(args).instantiate(providers.getMetaAccess(), loadExceptionObject, DEFAULT_REPLACER, args); } diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/MonitorSnippets.java Mon Jan 06 14:30:23 2014 -0800 @@ -422,16 +422,16 @@ this.useFastLocking = useFastLocking; } - public void lower(MonitorEnterNode monitorenterNode, HotSpotRegistersProvider registers) { + public void lower(MonitorEnterNode monitorenterNode, HotSpotRegistersProvider registers, LoweringTool tool) { StructuredGraph graph = monitorenterNode.graph(); - checkBalancedMonitors(graph); + checkBalancedMonitors(graph, tool); FrameState stateAfter = monitorenterNode.stateAfter(); Arguments args; if (useFastLocking) { - args = new Arguments(monitorenter, graph.getGuardsStage()); + args = new Arguments(monitorenter, graph.getGuardsStage(), tool.getLoweringStage()); } else { - args = new Arguments(monitorenterStub, graph.getGuardsStage()); + args = new Arguments(monitorenterStub, graph.getGuardsStage(), tool.getLoweringStage()); } args.add("object", monitorenterNode.object()); args.addConst("lockDepth", monitorenterNode.getLockDepth()); @@ -450,15 +450,15 @@ } } - public void lower(MonitorExitNode monitorexitNode, @SuppressWarnings("unused") LoweringTool tool) { + public void lower(MonitorExitNode monitorexitNode, LoweringTool tool) { StructuredGraph graph = monitorexitNode.graph(); FrameState stateAfter = monitorexitNode.stateAfter(); Arguments args; if (useFastLocking) { - args = new Arguments(monitorexit, graph.getGuardsStage()); + args = new Arguments(monitorexit, graph.getGuardsStage(), tool.getLoweringStage()); } else { - args = new Arguments(monitorexitStub, graph.getGuardsStage()); + args = new Arguments(monitorexitStub, graph.getGuardsStage(), tool.getLoweringStage()); } args.add("object", monitorexitNode.object()); args.addConst("lockDepth", monitorexitNode.getLockDepth()); @@ -507,7 +507,7 @@ * If balanced monitor checking is enabled then nodes are inserted at the start and all * return points of the graph to initialize and check the monitor counter respectively. */ - private void checkBalancedMonitors(StructuredGraph graph) { + private void checkBalancedMonitors(StructuredGraph graph, LoweringTool tool) { if (CHECK_BALANCED_MONITORS) { NodeIterable nodes = graph.getNodes().filter(MonitorCounterNode.class); if (nodes.isEmpty()) { @@ -533,7 +533,7 @@ invoke.setStateAfter(graph.add(stateAfter)); graph.addBeforeFixed(ret, invoke); - Arguments args = new Arguments(checkCounter, graph.getGuardsStage()); + Arguments args = new Arguments(checkCounter, graph.getGuardsStage(), tool.getLoweringStage()); args.addConst("errMsg", msg); inlineeGraph = template(args).copySpecializedGraph(); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Mon Jan 06 14:30:23 2014 -0800 @@ -46,6 +46,7 @@ import com.oracle.graal.nodes.debug.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.options.*; import com.oracle.graal.phases.util.*; @@ -307,14 +308,14 @@ /** * Lowers a {@link NewInstanceNode}. */ - public void lower(NewInstanceNode newInstanceNode, HotSpotRegistersProvider registers) { + public void lower(NewInstanceNode newInstanceNode, HotSpotRegistersProvider registers, LoweringTool tool) { StructuredGraph graph = newInstanceNode.graph(); HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) newInstanceNode.instanceClass(); assert !type.isArray(); ConstantNode hub = ConstantNode.forConstant(type.klass(), providers.getMetaAccess(), graph); int size = instanceSize(type); - Arguments args = new Arguments(allocateInstance, graph.getGuardsStage()); + Arguments args = new Arguments(allocateInstance, graph.getGuardsStage(), tool.getLoweringStage()); args.addConst("size", size); args.add("hub", hub); args.add("prototypeMarkWord", type.prototypeMarkWord()); @@ -330,7 +331,7 @@ /** * Lowers a {@link NewArrayNode}. */ - public void lower(NewArrayNode newArrayNode, HotSpotRegistersProvider registers) { + public void lower(NewArrayNode newArrayNode, HotSpotRegistersProvider registers, LoweringTool tool) { StructuredGraph graph = newArrayNode.graph(); ResolvedJavaType elementType = newArrayNode.elementType(); HotSpotResolvedObjectType arrayType = (HotSpotResolvedObjectType) elementType.getArrayClass(); @@ -340,7 +341,7 @@ HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer(); int log2ElementSize = CodeUtil.log2(lowerer.getScalingFactor(elementKind)); - Arguments args = new Arguments(allocateArray, graph.getGuardsStage()); + Arguments args = new Arguments(allocateArray, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); args.add("length", newArrayNode.length()); args.add("prototypeMarkWord", arrayType.prototypeMarkWord()); @@ -355,8 +356,8 @@ template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args); } - public void lower(DynamicNewArrayNode newArrayNode, HotSpotRegistersProvider registers) { - Arguments args = new Arguments(allocateArrayDynamic, newArrayNode.graph().getGuardsStage()); + public void lower(DynamicNewArrayNode newArrayNode, HotSpotRegistersProvider registers, LoweringTool tool) { + Arguments args = new Arguments(allocateArrayDynamic, newArrayNode.graph().getGuardsStage(), tool.getLoweringStage()); args.add("elementType", newArrayNode.getElementType()); args.add("length", newArrayNode.length()); args.addConst("fillContents", newArrayNode.fillContents()); @@ -366,7 +367,7 @@ template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args); } - public void lower(NewMultiArrayNode newmultiarrayNode) { + public void lower(NewMultiArrayNode newmultiarrayNode, LoweringTool tool) { StructuredGraph graph = newmultiarrayNode.graph(); int rank = newmultiarrayNode.dimensionCount(); ValueNode[] dims = new ValueNode[rank]; @@ -376,7 +377,7 @@ HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) newmultiarrayNode.type(); ConstantNode hub = ConstantNode.forConstant(type.klass(), providers.getMetaAccess(), graph); - Arguments args = new Arguments(newmultiarray, graph.getGuardsStage()); + Arguments args = new Arguments(newmultiarray, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); args.addConst("rank", rank); args.addVarargs("dimensions", int.class, StampFactory.forKind(Kind.Int), dims); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopyNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -95,7 +95,7 @@ public void lower(LoweringTool tool) { if (graph().getGuardsStage() == StructuredGraph.GuardsStage.AFTER_FSA) { UnsafeArrayCopySnippets.Templates templates = tool.getReplacements().getSnippetTemplateCache(UnsafeArrayCopySnippets.Templates.class); - templates.lower(this); + templates.lower(this, tool); } } diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeArrayCopySnippets.java Mon Jan 06 14:30:23 2014 -0800 @@ -33,6 +33,7 @@ import com.oracle.graal.asm.*; import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.Fold; @@ -265,7 +266,7 @@ genericPrimitiveSnippet = snippet(UnsafeArrayCopySnippets.class, "arraycopyPrimitive"); } - public void lower(UnsafeArrayCopyNode node) { + public void lower(UnsafeArrayCopyNode node, LoweringTool tool) { Kind elementKind = node.getElementKind(); SnippetInfo snippet; if (elementKind == null) { @@ -276,7 +277,7 @@ assert snippet != null : "arraycopy snippet for " + elementKind.name() + " not found"; } - Arguments args = new Arguments(snippet, node.graph().getGuardsStage()); + Arguments args = new Arguments(snippet, node.graph().getGuardsStage(), tool.getLoweringStage()); node.addSnippetArguments(args); SnippetTemplate template = template(args); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/UnsafeLoadSnippets.java Mon Jan 06 14:30:23 2014 -0800 @@ -56,8 +56,8 @@ super(providers, target); } - public void lower(UnsafeLoadNode load, @SuppressWarnings("unused") LoweringTool tool) { - Arguments args = new Arguments(unsafeLoad, load.graph().getGuardsStage()); + public void lower(UnsafeLoadNode load, LoweringTool tool) { + Arguments args = new Arguments(unsafeLoad, load.graph().getGuardsStage(), tool.getLoweringStage()); args.add("object", load.object()); args.add("offset", load.offset()); template(args).instantiate(providers.getMetaAccess(), load, DEFAULT_REPLACER, args); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/WriteBarrierSnippets.java Mon Jan 06 14:30:23 2014 -0800 @@ -36,6 +36,7 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.HeapAccess.BarrierType; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.*; @@ -333,28 +334,28 @@ super(providers, target); } - public void lower(SerialWriteBarrier writeBarrier) { + public void lower(SerialWriteBarrier writeBarrier, LoweringTool tool) { if (writeBarrier.alwaysNull()) { writeBarrier.graph().removeFixed(writeBarrier); return; } - Arguments args = new Arguments(serialWriteBarrier, writeBarrier.graph().getGuardsStage()); + Arguments args = new Arguments(serialWriteBarrier, writeBarrier.graph().getGuardsStage(), tool.getLoweringStage()); args.add("object", writeBarrier.getObject()); args.add("location", writeBarrier.getLocation()); args.addConst("usePrecise", writeBarrier.usePrecise()); template(args).instantiate(providers.getMetaAccess(), writeBarrier, DEFAULT_REPLACER, args); } - public void lower(SerialArrayRangeWriteBarrier arrayRangeWriteBarrier) { - Arguments args = new Arguments(serialArrayRangeWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage()); + public void lower(SerialArrayRangeWriteBarrier arrayRangeWriteBarrier, LoweringTool tool) { + Arguments args = new Arguments(serialArrayRangeWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage(), tool.getLoweringStage()); args.add("object", arrayRangeWriteBarrier.getObject()); args.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); args.add("length", arrayRangeWriteBarrier.getLength()); template(args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args); } - public void lower(G1PreWriteBarrier writeBarrierPre, HotSpotRegistersProvider registers) { - Arguments args = new Arguments(g1PreWriteBarrier, writeBarrierPre.graph().getGuardsStage()); + public void lower(G1PreWriteBarrier writeBarrierPre, HotSpotRegistersProvider registers, LoweringTool tool) { + Arguments args = new Arguments(g1PreWriteBarrier, writeBarrierPre.graph().getGuardsStage(), tool.getLoweringStage()); args.add("object", writeBarrierPre.getObject()); args.add("expectedObject", writeBarrierPre.getExpectedObject()); args.add("location", writeBarrierPre.getLocation()); @@ -365,8 +366,8 @@ template(args).instantiate(providers.getMetaAccess(), writeBarrierPre, DEFAULT_REPLACER, args); } - public void lower(G1ReferentFieldReadBarrier readBarrier, HotSpotRegistersProvider registers) { - Arguments args = new Arguments(g1ReferentReadBarrier, readBarrier.graph().getGuardsStage()); + public void lower(G1ReferentFieldReadBarrier readBarrier, HotSpotRegistersProvider registers, LoweringTool tool) { + Arguments args = new Arguments(g1ReferentReadBarrier, readBarrier.graph().getGuardsStage(), tool.getLoweringStage()); args.add("object", readBarrier.getObject()); args.add("expectedObject", readBarrier.getExpectedObject()); args.add("location", readBarrier.getLocation()); @@ -377,12 +378,12 @@ template(args).instantiate(providers.getMetaAccess(), readBarrier, DEFAULT_REPLACER, args); } - public void lower(G1PostWriteBarrier writeBarrierPost, HotSpotRegistersProvider registers) { + public void lower(G1PostWriteBarrier writeBarrierPost, HotSpotRegistersProvider registers, LoweringTool tool) { if (writeBarrierPost.alwaysNull()) { writeBarrierPost.graph().removeFixed(writeBarrierPost); return; } - Arguments args = new Arguments(g1PostWriteBarrier, writeBarrierPost.graph().getGuardsStage()); + Arguments args = new Arguments(g1PostWriteBarrier, writeBarrierPost.graph().getGuardsStage(), tool.getLoweringStage()); args.add("object", writeBarrierPost.getObject()); args.add("value", writeBarrierPost.getValue()); args.add("location", writeBarrierPost.getLocation()); @@ -392,8 +393,8 @@ template(args).instantiate(providers.getMetaAccess(), writeBarrierPost, DEFAULT_REPLACER, args); } - public void lower(G1ArrayRangePreWriteBarrier arrayRangeWriteBarrier, HotSpotRegistersProvider registers) { - Arguments args = new Arguments(g1ArrayRangePreWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage()); + public void lower(G1ArrayRangePreWriteBarrier arrayRangeWriteBarrier, HotSpotRegistersProvider registers, LoweringTool tool) { + Arguments args = new Arguments(g1ArrayRangePreWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage(), tool.getLoweringStage()); args.add("object", arrayRangeWriteBarrier.getObject()); args.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); args.add("length", arrayRangeWriteBarrier.getLength()); @@ -401,8 +402,8 @@ template(args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args); } - public void lower(G1ArrayRangePostWriteBarrier arrayRangeWriteBarrier, HotSpotRegistersProvider registers) { - Arguments args = new Arguments(g1ArrayRangePostWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage()); + public void lower(G1ArrayRangePostWriteBarrier arrayRangeWriteBarrier, HotSpotRegistersProvider registers, LoweringTool tool) { + Arguments args = new Arguments(g1ArrayRangePostWriteBarrier, arrayRangeWriteBarrier.graph().getGuardsStage(), tool.getLoweringStage()); args.add("object", arrayRangeWriteBarrier.getObject()); args.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); args.add("length", arrayRangeWriteBarrier.getLength()); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Mon Jan 06 14:30:23 2014 -0800 @@ -37,6 +37,7 @@ import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.StructuredGraph.GuardsStage; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; import com.oracle.graal.replacements.Snippet.Fold; @@ -66,7 +67,7 @@ Constant intArrayHub = intArrayType.klass(); intArrayHub = Constant.forIntegerKind(runtime().getTarget().wordKind, intArrayHub.asLong(), null); - Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS); + Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS, LoweringTool.StandardLoweringStage.HIGH_TIER); args.add("hub", null); args.add("length", null); args.addConst("intArrayHub", intArrayHub); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Mon Jan 06 14:30:23 2014 -0800 @@ -38,6 +38,7 @@ import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.replacements.*; import com.oracle.graal.nodes.StructuredGraph.GuardsStage; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.ConstantParameter; import com.oracle.graal.replacements.Snippet.Fold; @@ -67,7 +68,7 @@ Constant intArrayHub = intArrayType.klass(); intArrayHub = Constant.forIntegerKind(runtime().getTarget().wordKind, intArrayHub.asLong(), null); - Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS); + Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS, LoweringTool.StandardLoweringStage.HIGH_TIER); args.add("hub", null); args.addConst("intArrayHub", intArrayHub); args.addConst("threadRegister", providers.getRegisters().getThreadRegister()); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/SnippetStub.java Mon Jan 06 14:30:23 2014 -0800 @@ -31,6 +31,7 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.GuardsStage; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; @@ -81,7 +82,7 @@ * Adds the arguments to this snippet stub. */ protected Arguments makeArguments(SnippetInfo stub) { - Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS); + Arguments args = new Arguments(stub, GuardsStage.FLOATING_GUARDS, LoweringTool.StandardLoweringStage.HIGH_TIER); for (int i = 0; i < stub.getParameterCount(); i++) { String name = stub.getParameterName(i); if (stub.isConstantParameter(i)) { diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Jan 06 14:30:23 2014 -0800 @@ -1203,33 +1203,39 @@ } } MethodCallTargetNode callTarget = currentGraph.add(createMethodCallTarget(invokeKind, targetMethod, args, returnType)); - createInvokeNode(callTarget, resultType); + + // be conservative if information was not recorded (could result in endless recompiles + // otherwise) + if (graphBuilderConfig.omitAllExceptionEdges() || (optimisticOpts.useExceptionProbability() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE)) { + createInvoke(callTarget, resultType); + } else { + assert bci() == currentBlock.endBci; + frameState.clearNonLiveLocals(currentBlock.localsLiveOut); + + InvokeWithExceptionNode invoke = createInvokeWithException(callTarget, resultType); + + Block nextBlock = currentBlock.successors.get(0); + invoke.setNext(createTarget(nextBlock, frameState)); + } } protected MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, JavaType returnType) { return new MethodCallTargetNode(invokeKind, targetMethod, args, returnType); } - protected Invoke createInvokeNode(CallTargetNode callTarget, Kind resultType) { - // be conservative if information was not recorded (could result in endless recompiles - // otherwise) - if (graphBuilderConfig.omitAllExceptionEdges() || (optimisticOpts.useExceptionProbability() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE)) { - InvokeNode invoke = new InvokeNode(callTarget, bci()); - frameState.pushReturn(resultType, append(invoke)); - return invoke; - } else { - assert bci() == currentBlock.endBci; - frameState.clearNonLiveLocals(currentBlock.localsLiveOut); + protected InvokeNode createInvoke(CallTargetNode callTarget, Kind resultType) { + InvokeNode invoke = append(new InvokeNode(callTarget, bci())); + frameState.pushReturn(resultType, invoke); + return invoke; + } - DispatchBeginNode exceptionEdge = handleException(null, bci()); - InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, bci())); - frameState.pushReturn(resultType, invoke); - Block nextBlock = currentBlock.successors.get(0); - - invoke.setNext(createTarget(nextBlock, frameState)); - invoke.setStateAfter(frameState.create(nextBlock.startBci)); - return invoke; - } + protected InvokeWithExceptionNode createInvokeWithException(CallTargetNode callTarget, Kind resultType) { + DispatchBeginNode exceptionEdge = handleException(null, bci()); + InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, bci())); + frameState.pushReturn(resultType, invoke); + Block nextBlock = currentBlock.successors.get(0); + invoke.setStateAfter(frameState.create(nextBlock.startBci)); + return invoke; } private void genReturn(ValueNode x) { diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Mon Jan 06 14:30:23 2014 -0800 @@ -42,7 +42,7 @@ public class AMD64ControlFlow { - public static class ReturnOp extends AMD64LIRInstruction { + public static class ReturnOp extends AMD64LIRInstruction implements BlockEndOp { @Use({REG, ILLEGAL}) protected Value x; public ReturnOp(Value x) { diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/ControlFlowOptimizer.java Mon Jan 06 14:30:23 2014 -0800 @@ -65,7 +65,7 @@ assert ((StandardOp.JumpOp) instructions.get(instructions.size() - 1)).destination().label() == ((StandardOp.LabelOp) lir.lir(block.getFirstSuccessor()).get(0)).getLabel() : "branch target must be the successor"; // Block must have exactly one successor. - return instructions.size() == 2 && !instructions.get(instructions.size() - 1).hasState(); + return instructions.size() == 2 && !instructions.get(instructions.size() - 1).hasState() && !block.isExceptionEntry(); } private static void deleteEmptyBlocks(LIR lir, List blocks) { diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; @@ -82,7 +83,7 @@ } } - public void lowerToIf() { + public void lowerToIf(LoweringTool tool) { FixedNode next = next(); setNext(null); DeoptimizeNode deopt = graph().add(new DeoptimizeNode(action, reason)); @@ -99,6 +100,8 @@ ((FixedWithNextNode) predecessor()).setNext(ifNode); this.replaceAtUsages(noDeoptSuccessor); GraphUtil.killWithUnusedFloatingInputs(this); + + deopt.lower(tool); } @Override diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -68,7 +68,7 @@ ValueAnchorNode newAnchor = graph().add(new ValueAnchorNode(guard.asNode())); graph().replaceFixedWithFixed(this, newAnchor); } else { - lowerToIf(); + lowerToIf(tool); } } diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java Mon Jan 06 14:30:23 2014 -0800 @@ -177,6 +177,7 @@ public StructuredGraph copy(String newName, ResolvedJavaMethod newMethod) { StructuredGraph copy = new StructuredGraph(newName, newMethod, graphId, entryBCI); + copy.setGuardsStage(getGuardsStage()); HashMap replacements = new HashMap<>(); replacements.put(start, copy.start); copy.addDuplicates(getNodes(), this, this.getNodeCount(), replacements); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -118,7 +118,7 @@ // both are virtual without identity: check contents assert stateX.getVirtualObject().entryCount() == 1 && stateY.getVirtualObject().entryCount() == 1; assert stateX.getVirtualObject().type() == stateY.getVirtualObject().type(); - assert stateX.getVirtualObject().entryKind(0) == Kind.Int || stateX.getVirtualObject().entryKind(0) == Kind.Long; + assert stateX.getVirtualObject().entryKind(0).getStackKind() == Kind.Int || stateX.getVirtualObject().entryKind(0) == Kind.Long; IntegerEqualsNode equals = new IntegerEqualsNode(stateX.getEntry(0), stateY.getEntry(0)); tool.addNode(equals); tool.replaceWithValue(equals); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -61,9 +61,7 @@ @Override public void lower(LoweringTool tool) { - if (graph().getGuardsStage().ordinal() >= StructuredGraph.GuardsStage.FIXED_DEOPTS.ordinal()) { - tool.getLowerer().lower(this, tool); - } + tool.getLowerer().lower(this, tool); } @Override diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -34,11 +34,7 @@ * allows unsafe casts "sideways" in the type hierarchy. It does not allow to "drop" type * information, i.e., an unsafe cast is removed if the input object has a more precise or equal type * than the type this nodes casts to. - * - * @deprecated use {@link PiNode}. */ - -@Deprecated public class UnsafeCastNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, GuardingNode, IterableNodeType, Canonicalizable, ValueProxy { @Input private ValueNode object; diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java Mon Jan 06 14:30:23 2014 -0800 @@ -55,4 +55,23 @@ FixedWithNextNode lastFixedNode(); GuardingNode getCurrentGuardAnchor(); + + /** + * Marker interface lowering stages. + */ + interface LoweringStage { + } + + /** + * The lowering stages used in a standard Graal phase plan. Lowering is called 3 times, during + * every tier of compilation. + */ + enum StandardLoweringStage implements LoweringStage { + HIGH_TIER, MID_TIER, LOW_TIER + } + + /** + * Returns current lowering stage. + */ + LoweringStage getLoweringStage(); } diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Mon Jan 06 14:30:23 2014 -0800 @@ -1368,7 +1368,9 @@ // get rid of memory kill AbstractBeginNode begin = invokeWithException.next(); if (begin instanceof KillingBeginNode) { - graph.addAfterFixed(begin, graph.add(new BeginNode())); + BeginNode newBegin = new BeginNode(); + graph.addAfterFixed(begin, graph.add(newBegin)); + begin.replaceAtUsages(newBegin); graph.removeFixed(begin); } } else { diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Mon Jan 06 14:30:23 2014 -0800 @@ -28,8 +28,8 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.Graph.Mark; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.StructuredGraph.GuardsStage; @@ -64,6 +64,11 @@ } @Override + public LoweringStage getLoweringStage() { + return loweringStage; + } + + @Override public ConstantReflectionProvider getConstantReflection() { return context.getConstantReflection(); } @@ -183,9 +188,11 @@ } private final CanonicalizerPhase canonicalizer; + private final LoweringTool.LoweringStage loweringStage; - public LoweringPhase(CanonicalizerPhase canonicalizer) { + public LoweringPhase(CanonicalizerPhase canonicalizer, LoweringTool.LoweringStage loweringStage) { this.canonicalizer = canonicalizer; + this.loweringStage = loweringStage; } /** diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64ConvertSnippets.java Mon Jan 06 14:30:23 2014 -0800 @@ -188,7 +188,7 @@ StructuredGraph graph = convert.graph(); - Arguments args = new Arguments(key, graph.getGuardsStage()); + Arguments args = new Arguments(key, graph.getGuardsStage(), tool.getLoweringStage()); args.add("input", convert.value()); args.add("result", graph.unique(new AMD64ConvertNode(convert.getFromKind(), convert.getToKind(), convert.value()))); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java Mon Jan 06 14:30:23 2014 -0800 @@ -221,7 +221,7 @@ if (canonical != null && !ImmutableCode.getValue()) { box.graph().replaceFloating(box, canonical); } else { - Arguments args = new Arguments(boxSnippets.get(box.getBoxingKind()), box.graph().getGuardsStage()); + Arguments args = new Arguments(boxSnippets.get(box.getBoxingKind()), box.graph().getGuardsStage(), tool.getLoweringStage()); args.add("value", box.getValue()); SnippetTemplate template = template(args); @@ -232,7 +232,7 @@ } public void lower(UnboxNode unbox, LoweringTool tool) { - Arguments args = new Arguments(unboxSnippets.get(unbox.getBoxingKind()), unbox.graph().getGuardsStage()); + Arguments args = new Arguments(unboxSnippets.get(unbox.getBoxingKind()), unbox.graph().getGuardsStage(), tool.getLoweringStage()); args.add("value", unbox.getValue()); SnippetTemplate template = template(args); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Mon Jan 06 14:30:23 2014 -0800 @@ -413,13 +413,7 @@ for (MethodCallTargetNode callTarget : graph.getNodes(MethodCallTargetNode.class)) { ResolvedJavaMethod callee = callTarget.targetMethod(); if (callee == method) { - final StructuredGraph originalGraph = new StructuredGraph(original); - MetaAccessProvider metaAccess = providers.getMetaAccess(); - ForeignCallsProvider foreignCalls = providers.getForeignCalls(); - new GraphBuilderPhase(metaAccess, foreignCalls, GraphBuilderConfiguration.getSnippetDefault(), OptimisticOptimizations.NONE).apply(originalGraph); - new WordTypeVerificationPhase(metaAccess, target.wordKind).apply(graph); - new WordTypeRewriterPhase(metaAccess, target.wordKind).apply(graph); - + final StructuredGraph originalGraph = buildInitialGraph(original); InliningUtil.inline(callTarget.invoke(), originalGraph, true); Debug.dump(graph, "after inlining %s", callee); diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Mon Jan 06 14:30:23 2014 -0800 @@ -185,9 +185,9 @@ protected int nextParamIdx; - public Arguments(SnippetInfo info, GuardsStage guardsStage) { + public Arguments(SnippetInfo info, GuardsStage guardsStage, LoweringTool.LoweringStage loweringStage) { this.info = info; - this.cacheKey = new CacheKey(info, guardsStage); + this.cacheKey = new CacheKey(info, guardsStage, loweringStage); this.values = new Object[info.getParameterCount()]; } @@ -319,11 +319,13 @@ private final ResolvedJavaMethod method; private final Object[] values; private final GuardsStage guardsStage; + private final LoweringTool.LoweringStage loweringStage; private int hash; - protected CacheKey(SnippetInfo info, GuardsStage guardsStage) { + protected CacheKey(SnippetInfo info, GuardsStage guardsStage, LoweringTool.LoweringStage loweringStage) { this.method = info.method; this.guardsStage = guardsStage; + this.loweringStage = loweringStage; this.values = new Object[info.getParameterCount()]; this.hash = info.method.hashCode() + 31 * guardsStage.hashCode(); } @@ -342,7 +344,7 @@ if (method != other.method) { return false; } - if (guardsStage != other.guardsStage) { + if (guardsStage != other.guardsStage || loweringStage != other.loweringStage) { return false; } for (int i = 0; i < values.length; i++) { @@ -584,7 +586,7 @@ } snippetCopy.setGuardsStage(guardsStage); try (Scope s = Debug.scope("LoweringSnippetTemplate", snippetCopy)) { - new LoweringPhase(new CanonicalizerPhase(true)).apply(snippetCopy, phaseContext); + new LoweringPhase(new CanonicalizerPhase(true), args.cacheKey.loweringStage).apply(snippetCopy, phaseContext); } catch (Throwable e) { throw Debug.handle(e); } diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -106,7 +106,7 @@ } } try (Scope s = Debug.scope("LoweringSnippetTemplate", replacementGraph)) { - new LoweringPhase(new CanonicalizerPhase(true)).apply(replacementGraph, c); + new LoweringPhase(new CanonicalizerPhase(true), tool.getLoweringStage()).apply(replacementGraph, c); } catch (Throwable e) { throw Debug.handle(e); } diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java --- a/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.truffle.test/src/com/oracle/graal/truffle/test/PartialEvaluationTest.java Mon Jan 06 14:30:23 2014 -0800 @@ -190,7 +190,7 @@ canonicalizer.apply(graph, context); new DeadCodeEliminationPhase().apply(graph); - new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, context); + new LoweringPhase(new CanonicalizerPhase(true), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); new DeadCodeEliminationPhase().apply(graph); return graph; diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Fri Jan 03 16:38:57 2014 -0800 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Mon Jan 06 14:30:23 2014 -0800 @@ -111,6 +111,19 @@ } /** + * Unsafe conversion from a Java long value to a {@link PointerBase pointer}. The parameter is + * treated as an unsigned 64-bit value (in contrast to the semantics of a Java long). + * + * @param val a 64 bit unsigned value + * @return the value cast to PointerBase + */ + @Operation(opcode = Opcode.FROM_UNSIGNED) + @SuppressWarnings("unchecked") + public static T pointer(long val) { + return (T) box(val); + } + + /** * Unsafe conversion from a Java int value to a Word. The parameter is treated as an unsigned * 32-bit value (in contrast to the semantics of a Java int). * diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/CoreSource.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/CoreSource.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes; + +import java.io.*; + +import com.oracle.truffle.api.*; + +/** + * Singleton source used for core method nodes. + */ +public final class CoreSource implements Source { + + private final String name; + + public CoreSource(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public String getCode() { + return name; + } + + @Override + public String toString() { + return name; + } + + public String getPath() { + return null; + } + + public Reader getReader() { + return null; + } + + public InputStream getInputStream() { + return null; + } + + public String getCode(int lineNumber) { + return null; + } + + public int getLineCount() { + return 0; + } + + public int getLineNumber(int offset) { + return 0; + } + + public int getLineStartOffset(int lineNumber) { + return 0; + } + + public int getLineLength(int lineNumber) { + return 0; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/CoreSourceSection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/CoreSourceSection.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes; + +import com.oracle.truffle.api.*; + +/** + * Singleton source section used for core method nodes. + */ +public final class CoreSourceSection implements SourceSection { + + private final String name; + + public CoreSourceSection(String name) { + this.name = name; + } + + public Source getSource() { + return new CoreSource(name); + } + + public int getStartLine() { + return 0; + } + + public int getStartColumn() { + return 0; + } + + public int getCharIndex() { + return 0; + } + + @Override + public int getCharLength() { + return 0; + } + + public int getCharEndIndex() { + return 0; + } + + public String getIdentifier() { + return null; + } + + public String getCode() { + return name; + } + + @Override + public String toString() { + return name; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/DefinedNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/DefinedNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * Switches execution to the parallel {@link RubyNode#isDefined} semantic path. Represents the + * {@code defined?} keyword in Ruby. + */ +@NodeInfo(shortName = "defined") +public class DefinedNode extends RubyNode { + + @Child protected RubyNode child; + + public DefinedNode(RubyContext context, SourceSection sourceSection, RubyNode child) { + super(context, sourceSection); + this.child = adoptChild(child); + } + + @Override + public Object execute(VirtualFrame frame) { + return child.isDefined(frame); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/InlinableMethodImplementation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/InlinableMethodImplementation.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.call.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +/** + * A method implementation that also carries the pristine root node and frame descriptor, from which + * we can inline. + * + * @see InlinedUnboxedDispatchNode + * @see InlinedBoxedDispatchNode + * @see InlineHeuristic + */ +public class InlinableMethodImplementation extends CallTargetMethodImplementation { + + private final FrameDescriptor frameDescriptor; + private final RubyRootNode pristineRootNode; + + public final boolean alwaysInline; + public final boolean shouldAppendCallNode; + + public InlinableMethodImplementation(CallTarget callTarget, MaterializedFrame declarationFrame, FrameDescriptor frameDescriptor, RubyRootNode pristineRootNode, boolean alwaysInline, + boolean shouldAppendCallNode) { + super(callTarget, declarationFrame); + + assert frameDescriptor != null; + assert pristineRootNode != null; + + this.frameDescriptor = frameDescriptor; + this.pristineRootNode = pristineRootNode; + this.alwaysInline = alwaysInline; + this.shouldAppendCallNode = shouldAppendCallNode; + } + + public FrameDescriptor getFrameDescriptor() { + return frameDescriptor; + } + + public RubyRootNode getPristineRootNode() { + return pristineRootNode; + } + + public RubyRootNode getCloneOfPristineRootNode() { + return NodeUtil.cloneNode(pristineRootNode); + } + + public boolean alwaysInline() { + return alwaysInline; + } + + public boolean getShouldAppendCallNode() { + return shouldAppendCallNode; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/ReadNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/ReadNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes; + +/** + * Interface for all nodes which read something, providing a method to transform them to write the + * same thing. + */ +public interface ReadNode { + + /** + * Return a new node that performs the equivalent write operation to this node's read, using the + * supplied node for the right-hand-side. + */ + RubyNode makeWriteNode(RubyNode rhs); + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/RubyNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/RubyNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes; + +import java.math.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.call.*; +import com.oracle.truffle.ruby.nodes.debug.*; +import com.oracle.truffle.ruby.nodes.yield.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; +import com.oracle.truffle.ruby.runtime.core.range.*; +import com.oracle.truffle.ruby.runtime.methods.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Base class for most nodes in Ruby. + * + * @see DispatchNode + * @see YieldDispatchNode + */ +@TypeSystemReference(RubyTypes.class) +public abstract class RubyNode extends Node { + + private final RubyContext context; + + public RubyNode(RubyContext context, SourceSection sourceSection) { + super(sourceSection); + + assert context != null; + assert sourceSection != null; + + this.context = context; + } + + public RubyNode(RubyNode prev) { + this(prev.context, prev.getSourceSection()); + } + + public abstract Object execute(VirtualFrame frame); + + /** + * Ruby's parallel semantic path. + * + * @see DefinedNode + */ + public Object isDefined(@SuppressWarnings("unused") VirtualFrame frame) { + throw new UnsupportedOperationException("no definition for " + getClass().getName()); + } + + public RubyArray executeArray(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyArray(execute(frame)); + } + + public BigInteger executeBignum(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectBigInteger(execute(frame)); + } + + public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectBoolean(execute(frame)); + } + + public RubyBignum executeBoxedBignum(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyBignum(execute(frame)); + } + + public RubyFixnum executeBoxedFixnum(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyFixnum(execute(frame)); + } + + public RubyFloat executeBoxedFloat(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyFloat(execute(frame)); + } + + public int executeFixnum(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectInteger(execute(frame)); + } + + public FixnumRange executeFixnumRange(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectFixnumRange(execute(frame)); + } + + public double executeFloat(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectDouble(execute(frame)); + } + + public NilPlaceholder executeNilPlaceholder(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectNilPlaceholder(execute(frame)); + } + + public Node executeNode(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectNode(execute(frame)); + } + + public Object[] executeObjectArray(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectObjectArray(execute(frame)); + } + + public ObjectRange executeObjectRange(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectObjectRange(execute(frame)); + } + + public RubyBasicObject executeRubyBasicObject(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyBasicObject(execute(frame)); + } + + public RubyBinding executeRubyBinding(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyBinding(execute(frame)); + } + + public RubyClass executeRubyClass(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyClass(execute(frame)); + } + + public RubyContinuation executeRubyContinuation(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyContinuation(execute(frame)); + } + + public RubyException executeRubyException(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyException(execute(frame)); + } + + public RubyFiber executeRubyFiber(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyFiber(execute(frame)); + } + + public RubyFile executeRubyFile(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyFile(execute(frame)); + } + + public RubyHash executeRubyHash(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyHash(execute(frame)); + } + + public RubyMatchData executeRubyMatchData(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyMatchData(execute(frame)); + } + + public RubyMethod executeRubyMethod(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyMethod(execute(frame)); + } + + public RubyModule executeRubyModule(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyModule(execute(frame)); + } + + public RubyNilClass executeRubyNilClass(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyNilClass(execute(frame)); + } + + public RubyObject executeRubyObject(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyObject(execute(frame)); + } + + public RubyProc executeRubyProc(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyProc(execute(frame)); + } + + public RubyRange executeRubyRange(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyRange(execute(frame)); + } + + public RubyRegexp executeRubyRegexp(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyRegexp(execute(frame)); + } + + public RubySymbol executeRubySymbol(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubySymbol(execute(frame)); + } + + public RubyThread executeRubyThread(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyThread(execute(frame)); + } + + public RubyTime executeRubyTime(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyTime(execute(frame)); + } + + public RubyString executeString(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectRubyString(execute(frame)); + } + + public UndefinedPlaceholder executeUndefinedPlaceholder(VirtualFrame frame) throws UnexpectedResultException { + return RubyTypesGen.RUBYTYPES.expectUndefinedPlaceholder(execute(frame)); + } + + public void executeVoid(VirtualFrame frame) { + execute(frame); + } + + /** + * If you aren't sure whether you have a normal {@link RubyNode} or a {@link RubyProxyNode}, + * this method will return the real node, whether that is this node, or whether this node is a + * proxy and you actually need the child. + */ + public RubyNode getNonProxyNode() { + return this; + } + + public RubyContext getContext() { + return context; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/RubyRootNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/RubyRootNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * The root node in an AST for a method. Unlike {@link RubyNode}, this has a single entry point, + * {@link #execute}, which Truffle knows about and can create a {@link CallTarget} from. + */ +public class RubyRootNode extends RootNode { + + protected final String indicativeName; + @Child protected RubyNode body; + + public RubyRootNode(SourceSection sourceSection, String indicativeName, RubyNode body) { + super(sourceSection); + + assert indicativeName != null; + assert body != null; + + this.body = adoptChild(body); + this.indicativeName = indicativeName; + } + + @Override + public Object execute(VirtualFrame frame) { + return body.execute(frame); + } + + @Override + public String toString() { + final SourceSection sourceSection = getSourceSection(); + final String source = sourceSection == null ? "" : sourceSection.toString(); + return "Method " + indicativeName + ":" + source + "@" + Integer.toHexString(hashCode()); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/RubyTypes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/RubyTypes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes; + +import java.math.*; + +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; +import com.oracle.truffle.ruby.runtime.core.range.*; +import com.oracle.truffle.ruby.runtime.methods.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * The list of types and type conversions that the AST interpreter knows about and can specialise + * using. Used by the DSL. + */ +@TypeSystem({UndefinedPlaceholder.class, // + NilPlaceholder.class, // + boolean.class, // + int.class, // + double.class, // + BigInteger.class, // + FixnumRange.class, // + ObjectRange.class, // + RubyArray.class, // + RubyBignum.class, // + RubyBinding.class, // + RubyClass.class, // + RubyContinuation.class, // + RubyException.class, // + RubyFiber.class, // + RubyFile.class, // + RubyFixnum.class, // + RubyFloat.class, // + RubyHash.class, // + RubyMatchData.class, // + RubyMethod.class, // + RubyModule.class, // + RubyNilClass.class, // + RubyProc.class, // + RubyRange.class, // + RubyRegexp.class, // + RubyString.class, // + RubySymbol.class, // + RubyThread.class, // + RubyTime.class, // + RubyObject.class, // + RubyBasicObject.class, // + Node.class, // + Object[].class}) +public class RubyTypes { + + /* + * The implicit casts allow the DSL to convert from an object of one type to another to satisfy + * specializations. + */ + + @ImplicitCast + public NilPlaceholder unboxNil(@SuppressWarnings("unused") RubyNilClass value) { + return NilPlaceholder.INSTANCE; + } + + @ImplicitCast + public int unboxFixnum(RubyFixnum value) { + return value.getValue(); + } + + @ImplicitCast + public BigInteger unboxBignum(RubyBignum value) { + return value.getValue(); + } + + @ImplicitCast + public double unboxFloat(RubyFloat value) { + return value.getValue(); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/WriteNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/WriteNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes; + +/** + * Interface for all nodes which write something, providing a method to transform them to read the + * same thing. + */ +public interface WriteNode { + + /** + * Return a new node that performs the equivalent read operation to this node's write. + */ + RubyNode makeReadNode(); + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/BooleanDispatchNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/BooleanDispatchNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.call; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +/** + * An unboxed node in the dispatch chain that dispatches if the node is a boolean. In normal unboxed + * dispatch we look at the Java class of the receiver. However, in Ruby true and false are two + * separate classes, so in this situation we have to dispatch on the value, as well as the Java + * class when we are dealing with booleans. + *

+ * TODO(CS): it would be nice if we could {@link RubyNode#executeBoolean} the receiver, but by the + * time we get to this dispatch node the receiver is already executed. + */ +public class BooleanDispatchNode extends UnboxedDispatchNode { + + private final Assumption falseUnmodifiedAssumption; + private final RubyMethod falseMethod; + + private final Assumption trueUnmodifiedAssumption; + private final RubyMethod trueMethod; + + @Child protected UnboxedDispatchNode next; + + public BooleanDispatchNode(RubyContext context, SourceSection sourceSection, Assumption falseUnmodifiedAssumption, RubyMethod falseMethod, Assumption trueUnmodifiedAssumption, + RubyMethod trueMethod, UnboxedDispatchNode next) { + super(context, sourceSection); + + assert falseUnmodifiedAssumption != null; + assert falseMethod != null; + assert trueUnmodifiedAssumption != null; + assert trueMethod != null; + + this.falseUnmodifiedAssumption = falseUnmodifiedAssumption; + this.falseMethod = falseMethod; + + this.trueUnmodifiedAssumption = trueUnmodifiedAssumption; + this.trueMethod = trueMethod; + + this.next = adoptChild(next); + } + + @Override + public Object dispatch(VirtualFrame frame, Object receiverObject, RubyProc blockObject, Object[] argumentsObjects) { + // Check it's a boolean + + if (!(receiverObject instanceof Boolean)) { + return next.dispatch(frame, receiverObject, blockObject, argumentsObjects); + } + + // Check the value + + Assumption unmodifiedAssumption; + RubyMethod method; + + if ((boolean) receiverObject) { + unmodifiedAssumption = trueUnmodifiedAssumption; + method = trueMethod; + } else { + unmodifiedAssumption = falseUnmodifiedAssumption; + method = falseMethod; + } + + // Check the class has not been modified + + try { + unmodifiedAssumption.check(); + } catch (InvalidAssumptionException e) { + return respecialize("class modified", frame, receiverObject, blockObject, argumentsObjects); + } + + // Call the method + + return method.call(frame.pack(), receiverObject, blockObject, argumentsObjects); + } + + @Override + public void setNext(UnboxedDispatchNode next) { + this.next = adoptChild(next); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/BoxedDispatchNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/BoxedDispatchNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.call; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * A node in the dispatch chain that expects the receiver to be an object boxed into a full + * {@link RubyBasicObject}. + */ +public abstract class BoxedDispatchNode extends DispatchNode { + + public BoxedDispatchNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public abstract Object dispatch(VirtualFrame frame, RubyBasicObject receiverObject, RubyProc blockObject, Object[] argumentsObjects); + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/BoxingDispatchNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/BoxingDispatchNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.call; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.utilities.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * A node in the dispatch chain that boxes the receiver into a full Ruby {@link RubyBasicObject}. + * This node is initially created as an {@link UninitializedBoxingDispatchNode} and only becomes + * this node when we know that we do need to box on the fast path. Within this node we specialized + * for the case that the receiver is always already boxed. + */ +public class BoxingDispatchNode extends UnboxedDispatchNode { + + @Child protected BoxedDispatchNode next; + + private final BranchProfile boxBranch = new BranchProfile(); + + public BoxingDispatchNode(RubyContext context, SourceSection sourceSection, BoxedDispatchNode next) { + super(context, sourceSection); + + this.next = adoptChild(next); + } + + @Override + public Object dispatch(VirtualFrame frame, Object receiverObject, RubyProc blockObject, Object[] argumentsObjects) { + RubyBasicObject boxedReceiverObject; + + if (receiverObject instanceof RubyBasicObject) { + boxedReceiverObject = (RubyBasicObject) receiverObject; + } else { + boxBranch.enter(); + boxedReceiverObject = getContext().getCoreLibrary().box(receiverObject); + } + + return next.dispatch(frame, boxedReceiverObject, blockObject, argumentsObjects); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/CachedBoxedDispatchNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/CachedBoxedDispatchNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.call; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.lookup.*; +import com.oracle.truffle.ruby.runtime.methods.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * A node in the dispatch chain that comes after the boxing point and caches a method on a full + * boxed Ruby BasicObject, matching it by looking at the lookup node and assuming it has not been + * modified. + */ +public class CachedBoxedDispatchNode extends BoxedDispatchNode { + + private final LookupNode expectedLookupNode; + private final Assumption unmodifiedAssumption; + private final RubyMethod method; + + @Child protected BoxedDispatchNode next; + + public CachedBoxedDispatchNode(RubyContext context, SourceSection sourceSection, LookupNode expectedLookupNode, RubyMethod method, BoxedDispatchNode next) { + super(context, sourceSection); + + assert expectedLookupNode != null; + assert method != null; + + this.expectedLookupNode = expectedLookupNode; + unmodifiedAssumption = expectedLookupNode.getUnmodifiedAssumption(); + this.method = method; + this.next = adoptChild(next); + } + + @Override + public Object dispatch(VirtualFrame frame, RubyBasicObject receiverObject, RubyProc blockObject, Object[] argumentsObjects) { + // Check the lookup node is what we expect + + if (receiverObject.getLookupNode() != expectedLookupNode) { + return next.dispatch(frame, receiverObject, blockObject, argumentsObjects); + } + + // Check the class has not been modified + + try { + unmodifiedAssumption.check(); + } catch (InvalidAssumptionException e) { + return respecialize("class modified", frame, receiverObject, blockObject, argumentsObjects); + } + + // Call the method + + return method.call(frame.pack(), receiverObject, blockObject, argumentsObjects); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/CachedUnboxedDispatchNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/CachedUnboxedDispatchNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.call; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +/** + * A node in the dispatch chain that comes before the boxing point and caches a method on a Java + * object, matching it by looking at the class and assuming it has not been modified. + */ +public class CachedUnboxedDispatchNode extends UnboxedDispatchNode { + + private final Class expectedClass; + private final Assumption unmodifiedAssumption; + private final RubyMethod method; + + @Child protected UnboxedDispatchNode next; + + public CachedUnboxedDispatchNode(RubyContext context, SourceSection sourceSection, Class expectedClass, Assumption unmodifiedAssumption, RubyMethod method, UnboxedDispatchNode next) { + super(context, sourceSection); + + assert expectedClass != null; + assert unmodifiedAssumption != null; + assert method != null; + + this.expectedClass = expectedClass; + this.unmodifiedAssumption = unmodifiedAssumption; + this.method = method; + this.next = adoptChild(next); + } + + @Override + public Object dispatch(VirtualFrame frame, Object receiverObject, RubyProc blockObject, Object[] argumentsObjects) { + // Check the class is what we expect + + if (receiverObject.getClass() != expectedClass) { + return next.dispatch(frame, receiverObject, blockObject, argumentsObjects); + } + + // Check the class has not been modified + + try { + unmodifiedAssumption.check(); + } catch (InvalidAssumptionException e) { + return respecialize("class modified", frame, receiverObject, blockObject, argumentsObjects); + } + + // Call the method + + return method.call(frame.pack(), receiverObject, blockObject, argumentsObjects); + } + + @Override + public void setNext(UnboxedDispatchNode next) { + this.next = adoptChild(next); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/CallNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/CallNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.call; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; +import com.oracle.truffle.ruby.runtime.methods.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * A call node that has a chain of dispatch nodes. + *

+ * The dispatch chain starts as {@link CallNode} -> {@link DispatchHeadNode} -> + * {@link UninitializedBoxingDispatchNode} -> {@link UninitializedDispatchNode}. + *

+ * When the {@link UninitializedDispatchNode} is reached a new node is inserted into the chain. If + * the node dispatches based on some unboxed value (unboxed as in it's not a Ruby object, just a + * Java object) such as {@link Integer}, then that node is inserted before the + * {@link UninitializedBoxingDispatchNode}, otherwise if it dispatches based on some Ruby + * BasicObject, it is inserted afterwards. + *

+ * The {@link UninitializedBoxingDispatchNode} becomes a {@link BoxingDispatchNode} when we find + * that the boxing has to be done on the fast path - when there is some boxed dispatch node. + *

+ * So the general format is {@link CallNode} -> {@link DispatchHeadNode} -> zero or more + * unboxed dispatches -> {@link UninitializedBoxingDispatchNode} | {@link BoxingDispatchNode} + * -> zero or more boxed dispatches -> {@link UninitializedDispatchNode}. + *

+ * There are several special cases of unboxed and boxed dispatch nodes based on the types and + * methods involved. + *

+ * If we have too many dispatch nodes we replace the whole chain with {@link DispatchHeadNode} -> + * {@link BoxingDispatchNode} -> {@link GeneralBoxedDispatchNode}. + *

+ * This system allows us to dispatch based purely on Java class, before we have to turn the object + * into a full {@link RubyBasicObject} and consider the full Ruby lookup process, and something such + * as a math call which may work on Fixnum or Float to work as just a couple of applications of + * {@code instanceof} and assumption checks. + */ +public class CallNode extends RubyNode { + + @Child protected RubyNode receiver; + @Child protected ProcOrNullNode block; + @Children protected final RubyNode[] arguments; + + private final String name; + private final boolean isSplatted; + + @Child protected DispatchHeadNode dispatchHead; + + public CallNode(RubyContext context, SourceSection section, String name, RubyNode receiver, RubyNode block, boolean isSplatted, RubyNode[] arguments) { + super(context, section); + + assert receiver != null; + assert arguments != null; + assert name != null; + + this.receiver = adoptChild(receiver); + + if (block == null) { + this.block = null; + } else { + this.block = adoptChild(ProcOrNullNodeFactory.create(context, section, block)); + } + + this.arguments = adoptChildren(arguments); + this.name = name; + this.isSplatted = isSplatted; + + dispatchHead = adoptChild(adoptChild(new DispatchHeadNode(context, section, name, isSplatted))); + } + + @Override + public Object execute(VirtualFrame frame) { + final Object receiverObject = receiver.execute(frame); + final Object[] argumentsObjects = executeArguments(frame); + final RubyProc blockObject = executeBlock(frame); + + return dispatchHead.dispatch(frame, receiverObject, blockObject, argumentsObjects); + } + + private RubyProc executeBlock(VirtualFrame frame) { + if (block != null) { + return block.executeRubyProc(frame); + } else { + return null; + } + } + + @ExplodeLoop + private Object[] executeArguments(VirtualFrame frame) { + final Object[] argumentsObjects = new Object[arguments.length]; + + for (int i = 0; i < arguments.length; i++) { + argumentsObjects[i] = arguments[i].execute(frame); + assert RubyContext.shouldObjectBeVisible(argumentsObjects[i]) : argumentsObjects[i].getClass(); + } + + if (isSplatted) { + assert argumentsObjects[0] instanceof RubyArray; + return ((RubyArray) argumentsObjects[0]).toObjectArray(); + } else { + return argumentsObjects; + } + } + + @Override + public Object isDefined(VirtualFrame frame) { + final RubyContext context = getContext(); + + Object receiverObject; + + try { + /* + * TODO(CS): Getting a node via an accessor like this doesn't work with Truffle at the + * moment and will cause frame escape errors, so we don't use it in compilation mode. + */ + + CompilerAsserts.neverPartOfCompilation(); + + receiverObject = receiver.execute(frame); + } catch (Exception e) { + return NilPlaceholder.INSTANCE; + } + + final RubyBasicObject receiverBasicObject = context.getCoreLibrary().box(receiverObject); + + final RubyMethod method = receiverBasicObject.getLookupNode().lookupMethod(name); + + final RubyBasicObject self = context.getCoreLibrary().box(frame.getArguments(RubyArguments.class).getSelf()); + + if (method == null || method.isUndefined()) { + return NilPlaceholder.INSTANCE; + } + + if (!method.isVisibleTo(self)) { + return NilPlaceholder.INSTANCE; + } + + return context.makeString("method"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/DispatchHeadNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/DispatchHeadNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.call; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.methods.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * The head of a chain of dispatch nodes. Can be used with {@link CallNode} or on its own. + */ +public class DispatchHeadNode extends DispatchNode { + + private final RubyContext context; + private final String name; + private final boolean isSplatted; + + @Child protected UnboxedDispatchNode dispatch; + + public DispatchHeadNode(RubyContext context, SourceSection sourceSection, String name, boolean isSplatted) { + super(context, sourceSection); + + assert context != null; + assert name != null; + + this.context = context; + this.name = name; + this.isSplatted = isSplatted; + + final UninitializedDispatchNode uninitializedDispatch = new UninitializedDispatchNode(context, sourceSection, name); + dispatch = adoptChild(new UninitializedBoxingDispatchNode(context, sourceSection, uninitializedDispatch)); + } + + public Object dispatch(VirtualFrame frame, Object receiverObject, RubyProc blockObject, Object... argumentsObjects) { + return dispatch.dispatch(frame, receiverObject, blockObject, argumentsObjects); + } + + /** + * Replace the entire dispatch chain with a fresh chain. Used when the situation has changed in + * such a significant way that it's best to start again rather than add new specializations to + * the chain. Used for example when methods appear to have been monkey-patched. + */ + public Object respecialize(VirtualFrame frame, String reason, Object receiverObject, RubyProc blockObject, Object... argumentObjects) { + CompilerAsserts.neverPartOfCompilation(); + + replace(new DispatchHeadNode(context, getSourceSection(), name, isSplatted), reason); + + final RubyBasicObject receiverBasicObject = context.getCoreLibrary().box(receiverObject); + + final RubyMethod method = lookup(frame, receiverBasicObject, name); + return method.call(frame.pack(), receiverBasicObject, blockObject, argumentObjects); + } + + public UnboxedDispatchNode getDispatch() { + return dispatch; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/DispatchNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/DispatchNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.call; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.methods.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Any node in the dispatch chain. + */ +public class DispatchNode extends Node { + + private final RubyContext context; + + public DispatchNode(RubyContext context, SourceSection sourceSection) { + super(sourceSection); + + assert context != null; + assert sourceSection != null; + + this.context = context; + } + + /** + * Get the depth of this node in the dispatch chain. The first node below + * {@link DispatchHeadNode} is at depth 1. + */ + public int getDepth() { + int depth = 1; + Node parent = this.getParent(); + + while (!(parent instanceof DispatchHeadNode)) { + parent = parent.getParent(); + depth++; + } + + return depth; + } + + public Object respecialize(String reason, VirtualFrame frame, Object receiverObject, RubyProc blockObject, Object... argumentsObjects) { + CompilerAsserts.neverPartOfCompilation(); + + final int depth = getDepth(); + final DispatchHeadNode head = (DispatchHeadNode) NodeUtil.getNthParent(this, depth); + + return head.respecialize(frame, reason, receiverObject, blockObject, argumentsObjects); + } + + /** + * The central point for method lookup. + */ + protected RubyMethod lookup(VirtualFrame frame, RubyBasicObject receiverBasicObject, String name) { + final RubyMethod method = receiverBasicObject.getLookupNode().lookupMethod(name); + + final RubyBasicObject self = context.getCoreLibrary().box(frame.getArguments(RubyArguments.class).getSelf()); + + if (method == null || method.isUndefined()) { + CompilerDirectives.transferToInterpreter(); + throw new RaiseException(context.getCoreLibrary().nameErrorNoMethod(name, receiverBasicObject.toString())); + } + + if (!method.isVisibleTo(self)) { + CompilerDirectives.transferToInterpreter(); + throw new RaiseException(context.getCoreLibrary().noMethodError(name, receiverBasicObject.toString())); + } + + return method; + } + + public RubyContext getContext() { + return context; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/GeneralBoxedDispatchNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/GeneralBoxedDispatchNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.call; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.methods.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * A node in the dispatch chain that does no caching and looks up methods from scratch each time it + * is called. + */ +public class GeneralBoxedDispatchNode extends BoxedDispatchNode { + + private final String name; + + public GeneralBoxedDispatchNode(RubyContext context, SourceSection sourceSection, String name) { + super(context, sourceSection); + + assert name != null; + + this.name = name; + } + + @Override + public Object dispatch(VirtualFrame frame, RubyBasicObject receiverObject, RubyProc blockObject, Object[] argumentsObjects) { + /* + * TODO(CS): we should probably have some kind of cache here - even if it's just a hash map. + * MRI and JRuby do and might avoid some pathological cases. + */ + + final RubyMethod method = lookup(frame, receiverObject, name); + return method.call(frame.pack(), receiverObject, blockObject, argumentsObjects); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/GeneralSuperCallNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/GeneralSuperCallNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.call; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; +import com.oracle.truffle.ruby.runtime.methods.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Represents a super call - that is a call with self as the receiver, but the superclass of self + * used for lookup. Currently implemented without any caching, and needs to be replaced with the + * same caching mechanism as for normal calls without complicating the existing calls too much. + */ +@NodeInfo(shortName = "general-super-call") +public class GeneralSuperCallNode extends RubyNode { + + private final String name; + private final boolean isSplatted; + @Child protected RubyNode block; + @Children protected final RubyNode[] arguments; + + public GeneralSuperCallNode(RubyContext context, SourceSection sourceSection, String name, RubyNode block, RubyNode[] arguments, boolean isSplatted) { + super(context, sourceSection); + + assert name != null; + assert arguments != null; + assert !isSplatted || arguments.length == 1; + + this.name = name; + this.block = adoptChild(block); + this.arguments = adoptChildren(arguments); + this.isSplatted = isSplatted; + } + + @ExplodeLoop + @Override + public final Object execute(VirtualFrame frame) { + // This method is only a simple implementation - it needs proper caching + + CompilerAsserts.neverPartOfCompilation(); + + final RubyBasicObject self = (RubyBasicObject) frame.getArguments(RubyArguments.class).getSelf(); + + // Execute the arguments + + final Object[] argumentsObjects = new Object[arguments.length]; + + CompilerAsserts.compilationConstant(arguments.length); + for (int i = 0; i < arguments.length; i++) { + argumentsObjects[i] = arguments[i].execute(frame); + } + + // Execute the block + + RubyProc blockObject; + + if (block != null) { + final Object blockTempObject = block.execute(frame); + + if (blockTempObject instanceof NilPlaceholder) { + blockObject = null; + } else { + blockObject = (RubyProc) blockTempObject; + } + } else { + blockObject = null; + } + + // Lookup method + + final RubyClass selfClass = self.getRubyClass(); + final RubyMethod method = selfClass.getSuperclass().lookupMethod(name); + + if (method == null || method.isUndefined()) { + CompilerDirectives.transferToInterpreter(); + throw new RaiseException(getContext().getCoreLibrary().nameErrorNoMethod(name, self.toString())); + } + + if (!method.isVisibleTo(self)) { + CompilerDirectives.transferToInterpreter(); + throw new RaiseException(getContext().getCoreLibrary().noMethodError("(unknown)")); + } + + // Call the method + + if (isSplatted) { + final RubyArray argumentsArray = (RubyArray) argumentsObjects[0]; + return method.call(frame.pack(), self, blockObject, argumentsArray.asList().toArray()); + } else { + return method.call(frame.pack(), self, blockObject, argumentsObjects); + } + } + + @Override + public Object isDefined(VirtualFrame frame) { + final RubyContext context = getContext(); + + try { + final RubyBasicObject self = context.getCoreLibrary().box(frame.getArguments(RubyArguments.class).getSelf()); + final RubyBasicObject receiverRubyObject = context.getCoreLibrary().box(self); + + final RubyMethod method = receiverRubyObject.getRubyClass().getSuperclass().lookupMethod(name); + + if (method == null || method.isUndefined() || !method.isVisibleTo(self)) { + return NilPlaceholder.INSTANCE; + } else { + return context.makeString("super"); + } + } catch (Exception e) { + return NilPlaceholder.INSTANCE; + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/InlineHeuristic.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/InlineHeuristic.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.call; + +import com.oracle.truffle.ruby.nodes.*; + +public class InlineHeuristic { + + public static boolean shouldInline(InlinableMethodImplementation method) { + if (method.alwaysInline()) { + return true; + } + + return false; + } + + public static boolean shouldInlineYield(@SuppressWarnings("unused") InlinableMethodImplementation method) { + return true; + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/InlinedBoxedDispatchNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/InlinedBoxedDispatchNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.call; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.lookup.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * A node in the dispatch chain that comes after the boxing point and caches a method on a full + * boxed {@link RubyBasicObject}, matching it by looking at the lookup node and assuming it has not + * been modified. + */ +public class InlinedBoxedDispatchNode extends BoxedDispatchNode { + + private final LookupNode expectedLookupNode; + private final Assumption unmodifiedAssumption; + + private final InlinableMethodImplementation method; + private final RubyRootNode rootNode; + + @Child protected BoxedDispatchNode next; + + public InlinedBoxedDispatchNode(RubyContext context, SourceSection sourceSection, LookupNode expectedLookupNode, InlinableMethodImplementation method, BoxedDispatchNode next) { + super(context, sourceSection); + + assert expectedLookupNode != null; + assert method != null; + + this.expectedLookupNode = expectedLookupNode; + unmodifiedAssumption = expectedLookupNode.getUnmodifiedAssumption(); + this.method = method; + this.rootNode = method.getCloneOfPristineRootNode(); + this.next = adoptChild(next); + } + + @Override + public Object dispatch(VirtualFrame frame, RubyBasicObject receiverObject, RubyProc blockObject, Object[] argumentsObjects) { + // Check the lookup node is what we expect + + if (receiverObject.getLookupNode() != expectedLookupNode) { + return next.dispatch(frame, receiverObject, blockObject, argumentsObjects); + } + + // Check the class has not been modified + + try { + unmodifiedAssumption.check(); + } catch (InvalidAssumptionException e) { + return respecialize("class modified", frame, receiverObject, blockObject, argumentsObjects); + } + + // Call the method + + Object[] modifiedArgumentsObjects; + + CompilerAsserts.compilationConstant(method.getShouldAppendCallNode()); + + if (method.getShouldAppendCallNode()) { + modifiedArgumentsObjects = Arrays.copyOf(argumentsObjects, argumentsObjects.length + 1); + modifiedArgumentsObjects[modifiedArgumentsObjects.length - 1] = this; + } else { + modifiedArgumentsObjects = argumentsObjects; + } + + final RubyArguments arguments = new RubyArguments(method.getDeclarationFrame(), receiverObject, blockObject, modifiedArgumentsObjects); + final VirtualFrame inlinedFrame = Truffle.getRuntime().createVirtualFrame(frame.pack(), arguments, method.getFrameDescriptor()); + return rootNode.execute(inlinedFrame); + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/InlinedUnboxedDispatchNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/InlinedUnboxedDispatchNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.call; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +public class InlinedUnboxedDispatchNode extends UnboxedDispatchNode { + + private final Class expectedClass; + private final Assumption unmodifiedAssumption; + + private final InlinableMethodImplementation method; + private final RubyRootNode rootNode; + + @Child protected UnboxedDispatchNode next; + + public InlinedUnboxedDispatchNode(RubyContext context, SourceSection sourceSection, Class expectedClass, Assumption unmodifiedAssumption, InlinableMethodImplementation method, + UnboxedDispatchNode next) { + super(context, sourceSection); + + assert expectedClass != null; + assert method != null; + + this.expectedClass = expectedClass; + this.unmodifiedAssumption = unmodifiedAssumption; + this.method = method; + this.rootNode = method.getCloneOfPristineRootNode(); + this.next = adoptChild(next); + } + + @Override + public Object dispatch(VirtualFrame frame, Object receiverObject, RubyProc blockObject, Object[] argumentsObjects) { + // Check the class is what we expect + + if (receiverObject.getClass() != expectedClass) { + return next.dispatch(frame, receiverObject, blockObject, argumentsObjects); + } + + // Check the class has not been modified + + try { + unmodifiedAssumption.check(); + } catch (InvalidAssumptionException e) { + return respecialize("class modified", frame, receiverObject, blockObject, argumentsObjects); + } + + // Call the method + + final RubyArguments arguments = new RubyArguments(method.getDeclarationFrame(), receiverObject, blockObject, argumentsObjects); + final VirtualFrame inlinedFrame = Truffle.getRuntime().createVirtualFrame(frame.pack(), arguments, method.getFrameDescriptor()); + return rootNode.execute(inlinedFrame); + } + + @Override + public void setNext(UnboxedDispatchNode next) { + this.next = adoptChild(next); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/ProcOrNullNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/ProcOrNullNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.call; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * Wraps some node that will produce either a {@link RubyProc} or a {@link NilPlaceholder} and + * returns {@code null} in case of the latter. Used in parts of the dispatch chain. + */ +@NodeInfo(shortName = "proc-or-null") +@NodeChild(value = "child", type = RubyNode.class) +public abstract class ProcOrNullNode extends RubyNode { + + public ProcOrNullNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ProcOrNullNode(ProcOrNullNode prev) { + super(prev); + } + + @Specialization + public Object doNil(@SuppressWarnings("unused") NilPlaceholder nil) { + return null; + } + + @Specialization + public Object doProc(RubyProc proc) { + return proc; + } + + @Override + public RubyProc executeRubyProc(VirtualFrame frame) { + final Object proc = execute(frame); + + // The standard asRubyProc test doesn't allow for null + assert proc == null || RubyTypesGen.RUBYTYPES.isRubyProc(proc); + + return (RubyProc) proc; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/UnboxedDispatchNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/UnboxedDispatchNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.call; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * A node in the dispatch chain that expects the receiver to be a simple Java object such as a boxed + * primitive, rather than a full {@link RubyBasicObject}. This allows calls to be made with a + * receiver such as {@link Integer} without having to turn it into a {@link RubyFixnum}. Followed at + * some point by an {@link UninitializedBoxingDispatchNode} or {@link BoxingDispatchNode} before we + * try to dispatch on a Ruby BasicObject or the {@link UninitializedDispatchNode}. + */ +public abstract class UnboxedDispatchNode extends DispatchNode { + + public UnboxedDispatchNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public abstract Object dispatch(VirtualFrame frame, Object receiverObject, RubyProc blockObject, Object[] argumentsObjects); + + public void setNext(@SuppressWarnings("unused") UnboxedDispatchNode next) { + throw new UnsupportedOperationException(); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/UninitializedBoxingDispatchNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/UninitializedBoxingDispatchNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.call; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * A node in the dispatch chain that transfers to interpreter and then boxes the receiver. + */ +public class UninitializedBoxingDispatchNode extends UnboxedDispatchNode { + + @Child protected BoxedDispatchNode next; + + public UninitializedBoxingDispatchNode(RubyContext context, SourceSection sourceSection, BoxedDispatchNode next) { + super(context, sourceSection); + + this.next = adoptChild(next); + } + + @Override + public Object dispatch(VirtualFrame frame, Object receiverObject, RubyProc blockObject, Object[] argumentsObjects) { + CompilerDirectives.transferToInterpreter(); + + /* + * If the next dispatch node is something other than the uninitialized dispatch node then we + * need to replace this node because it's now on the fast path. If the receiver was already + * boxed. + * + * Note that with this scheme it will take a couple of calls for the chain to become fully + * specialized. + */ + + if (next instanceof UninitializedDispatchNode) { + this.replace(new BoxingDispatchNode(getContext(), getSourceSection(), next)); + } + + return next.dispatch(frame, getContext().getCoreLibrary().box(receiverObject), blockObject, argumentsObjects); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/UninitializedDispatchNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/call/UninitializedDispatchNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.call; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.methods.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * The uninitialized dispatch node. Only reached when the method is not expected by any node in the + * dispatch chain, and only creates new nodes or modifies the existing chain. + */ +public class UninitializedDispatchNode extends BoxedDispatchNode { + + /* + * Node at depth 5 is 4 actual dispatches, the boxing dispatch and the final uninitalized + * dispatch. + */ + + private static final int MAX_DEPTH = 5; + + private final String name; + + public UninitializedDispatchNode(RubyContext context, SourceSection sourceSection, String name) { + super(context, sourceSection); + + assert name != null; + + this.name = name; + } + + @Override + public Object dispatch(VirtualFrame frame, RubyBasicObject receiverObject, RubyProc blockObject, Object[] argumentsObjects) { + CompilerDirectives.transferToInterpreter(); + + final RubyContext context = getContext(); + + final RubyMethod method = lookup(frame, receiverObject, name); + + final int depth = getDepth(); + + final DispatchHeadNode dispatchHead = (DispatchHeadNode) NodeUtil.getNthParent(this, depth); + + if (depth == MAX_DEPTH) { + /* + * Replace the chain with DispatchHeadNode -> ExpectBoxedDispatchNode -> + * GeneralDispatchNode. + */ + + context.implementationMessage("resorting to a general call node at %s", getSourceSection()); + NodeUtil.printTree(System.err, dispatchHead); + + final GeneralBoxedDispatchNode newGeneralDispatch = new GeneralBoxedDispatchNode(getContext(), getSourceSection(), name); + final BoxingDispatchNode newBoxing = new BoxingDispatchNode(getContext(), getSourceSection(), newGeneralDispatch); + + dispatchHead.getDispatch().replace(newBoxing); + return newBoxing.dispatch(frame, receiverObject, blockObject, argumentsObjects); + } else if (receiverObject instanceof Unboxable) { + /* + * Unboxed dispatch nodes are prepended to the chain of dispatch nodes, so they're + * before the point where receivers will definitely be boxed. + */ + + final Object receiverUnboxed = ((Unboxable) receiverObject).unbox(); + + final UnboxedDispatchNode firstDispatch = dispatchHead.getDispatch(); + + if (receiverObject instanceof RubyTrueClass || receiverObject instanceof RubyFalseClass) { + final Assumption falseUnmodifiedAssumption = context.getCoreLibrary().getFalseClass().getUnmodifiedAssumption(); + final RubyMethod falseMethod = lookup(frame, context.getCoreLibrary().box(false), name); + final Assumption trueUnmodifiedAssumption = context.getCoreLibrary().getTrueClass().getUnmodifiedAssumption(); + final RubyMethod trueMethod = lookup(frame, context.getCoreLibrary().box(true), name); + + final BooleanDispatchNode newDispatch = new BooleanDispatchNode(getContext(), getSourceSection(), falseUnmodifiedAssumption, falseMethod, trueUnmodifiedAssumption, trueMethod, null); + firstDispatch.replace(newDispatch, "prepending new unboxed dispatch node to chain"); + newDispatch.setNext(firstDispatch); + return newDispatch.dispatch(frame, receiverUnboxed, blockObject, argumentsObjects); + } else { + UnboxedDispatchNode newDispatch; + + if (method.getImplementation() instanceof InlinableMethodImplementation && InlineHeuristic.shouldInline((InlinableMethodImplementation) method.getImplementation())) { + newDispatch = new InlinedUnboxedDispatchNode(getContext(), getSourceSection(), receiverUnboxed.getClass(), receiverObject.getRubyClass().getUnmodifiedAssumption(), + (InlinableMethodImplementation) method.getImplementation(), null); + } else { + newDispatch = new CachedUnboxedDispatchNode(getContext(), getSourceSection(), receiverUnboxed.getClass(), receiverObject.getRubyClass().getUnmodifiedAssumption(), method, null); + } + + firstDispatch.replace(newDispatch, "prepending new unboxed dispatch node to chain"); + newDispatch.setNext(firstDispatch); + + return newDispatch.dispatch(frame, receiverUnboxed, blockObject, argumentsObjects); + } + } else { + /* + * Boxed dispatch nodes are appended to the chain of dispatch nodes, so they're after + * the point where receivers are guaranteed to be boxed. + */ + + final UninitializedDispatchNode newUninitializedDispatch = new UninitializedDispatchNode(getContext(), getSourceSection(), name); + + BoxedDispatchNode newDispatch; + + if (method.getImplementation() instanceof InlinableMethodImplementation && InlineHeuristic.shouldInline((InlinableMethodImplementation) method.getImplementation())) { + newDispatch = new InlinedBoxedDispatchNode(getContext(), getSourceSection(), receiverObject.getLookupNode(), (InlinableMethodImplementation) method.getImplementation(), + newUninitializedDispatch); + } else { + newDispatch = new CachedBoxedDispatchNode(getContext(), getSourceSection(), receiverObject.getLookupNode(), method, newUninitializedDispatch); + } + + replace(newDispatch, "appending new boxed dispatch node to chain"); + + return newDispatch.dispatch(frame, receiverObject, blockObject, argumentsObjects); + } + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/cast/BooleanCastNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/cast/BooleanCastNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.cast; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * Casts a value into a boolean. Works at the language level, so doesn't call any Ruby methods to + * cast non-core or monkey-patched objects. + */ +@NodeInfo(shortName = "cast-boolean") +@NodeChild(value = "child", type = RubyNode.class) +public abstract class BooleanCastNode extends RubyNode { + + public BooleanCastNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public BooleanCastNode(BooleanCastNode copy) { + super(copy.getContext(), copy.getSourceSection()); + } + + @Specialization + public boolean doBoolean(boolean value) { + return value; + } + + @Specialization + public boolean doNil(@SuppressWarnings("unused") NilPlaceholder nil) { + return false; + } + + @Generic + public boolean doGeneric(Object object) { + if (object instanceof Boolean) { + return (boolean) object; + } else if (object instanceof NilPlaceholder || object instanceof RubyNilClass) { + return false; + } else { + return true; + } + } + + @Override + public abstract boolean executeBoolean(VirtualFrame frame); + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/cast/LambdaNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/cast/LambdaNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.cast; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +@NodeInfo(shortName = "lambda") +public class LambdaNode extends RubyNode { + + @Child private RubyNode definition; + + public LambdaNode(RubyContext context, SourceSection sourceSection, RubyNode definition) { + super(context, sourceSection); + this.definition = adoptChild(definition); + } + + @Override + public Object execute(VirtualFrame frame) { + return new RubyProc(getContext().getCoreLibrary().getProcClass(), RubyProc.Type.LAMBDA, frame.getArguments(RubyArguments.class).getSelf(), null, (RubyMethod) definition.execute(frame)); + } + + @Override + public void executeVoid(VirtualFrame frame) { + definition.executeVoid(frame); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/cast/ProcCastNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/cast/ProcCastNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.cast; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.nodes.call.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Casts an object to a Ruby Proc object. + */ +@NodeInfo(shortName = "cast-proc") +@NodeChild("child") +public abstract class ProcCastNode extends RubyNode { + + @Child protected DispatchHeadNode toProc; + + public ProcCastNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + toProc = adoptChild(new DispatchHeadNode(context, getSourceSection(), "to_proc", false)); + } + + public ProcCastNode(ProcCastNode prev) { + super(prev); + toProc = adoptChild(prev.toProc); + } + + @Specialization + public NilPlaceholder doNil(NilPlaceholder nil) { + return nil; + } + + @Specialization + public RubyProc doRubyProc(RubyProc proc) { + return proc; + } + + @Specialization + public RubyProc doObject(VirtualFrame frame, RubyBasicObject object) { + return (RubyProc) toProc.dispatch(frame, object, null); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/cast/SplatCastNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/cast/SplatCastNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.cast; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +/** + * Splat as used to cast a value to an array if it isn't already, as in {@code *value}. + */ +@NodeInfo(shortName = "cast-splat") +@NodeChild("child") +public abstract class SplatCastNode extends RubyNode { + + public SplatCastNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SplatCastNode(SplatCastNode prev) { + super(prev); + } + + protected abstract RubyNode getChild(); + + @Specialization + public RubyArray doArray(RubyArray array) { + return array; + } + + @Specialization + public RubyArray doObject(Object object) { + if (object instanceof RubyArray) { + return (RubyArray) object; + } else { + return RubyArray.specializedFromObject(getContext().getCoreLibrary().getArrayClass(), object); + } + } + + @Override + public void executeVoid(VirtualFrame frame) { + getChild().executeVoid(frame); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/cast/StringToRegexpNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/cast/StringToRegexpNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.cast; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * Creates a regex from a string. + */ +@NodeInfo(shortName = "cast-string-to-regexp") +@NodeChild("string") +public abstract class StringToRegexpNode extends RubyNode { + + public StringToRegexpNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public StringToRegexpNode(StringToRegexpNode prev) { + super(prev); + } + + @Specialization + public RubyRegexp doString(RubyString string) { + return new RubyRegexp(getContext().getCoreLibrary().getRegexpClass(), string.toString()); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/cast/StringToSymbolNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/cast/StringToSymbolNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.cast; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * Creates a symbol from a string. + */ +@NodeInfo(shortName = "cast-string-to-symbol") +@NodeChild("string") +public abstract class StringToSymbolNode extends RubyNode { + + public StringToSymbolNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public StringToSymbolNode(StringToSymbolNode prev) { + super(prev); + } + + @Specialization + public RubySymbol doString(RubyString string) { + return new RubySymbol(getContext().getCoreLibrary().getSymbolClass(), string.toString()); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/constants/CachedReadConstantNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/constants/CachedReadConstantNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.constants; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.utilities.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Represents a constant read from some object and cached, with the assumption that the object it + * was read from is unmodified. If that assumption does not hold the read is uninitialized. If the + * class of the receiver changes we also uninitialize. + */ +@NodeInfo(shortName = "cached-read-constant") +public class CachedReadConstantNode extends ReadConstantNode { + + private final RubyClass expectedClass; + private final Assumption unmodifiedAssumption; + + private final Object value; + + private final boolean hasBoolean; + private final boolean booleanValue; + + private final boolean hasInt; + private final int intValue; + + private final boolean hasDouble; + private final double doubleValue; + + private final BranchProfile boxBranchProfile = new BranchProfile(); + + public CachedReadConstantNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver, RubyClass expectedClass, Object value) { + super(context, sourceSection, name, receiver); + + this.expectedClass = expectedClass; + unmodifiedAssumption = expectedClass.getUnmodifiedAssumption(); + + this.value = value; + + /* + * We could do this lazily as needed, but I'm sure the compiler will appreciate the fact + * that these fields are all final. + */ + + if (value instanceof Boolean) { + hasBoolean = true; + booleanValue = (boolean) value; + + hasInt = false; + intValue = -1; + + hasDouble = false; + doubleValue = -1; + } else if (value instanceof Integer) { + hasBoolean = false; + booleanValue = false; + + hasInt = true; + intValue = (int) value; + + hasDouble = true; + doubleValue = (int) value; + } else if (value instanceof Double) { + hasBoolean = false; + booleanValue = false; + + hasInt = false; + intValue = -1; + + hasDouble = true; + doubleValue = (double) value; + } else { + hasBoolean = false; + booleanValue = false; + + hasInt = false; + intValue = -1; + + hasDouble = false; + doubleValue = -1; + } + } + + @Override + public Object execute(VirtualFrame frame) { + try { + guard(frame); + } catch (UnexpectedResultException e) { + return e.getResult(); + } + + return value; + } + + @Override + public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException { + guard(frame); + + if (hasBoolean) { + return booleanValue; + } else { + throw new UnexpectedResultException(value); + } + } + + @Override + public int executeFixnum(VirtualFrame frame) throws UnexpectedResultException { + guard(frame); + + if (hasInt) { + return intValue; + } else { + throw new UnexpectedResultException(value); + } + } + + @Override + public double executeFloat(VirtualFrame frame) throws UnexpectedResultException { + guard(frame); + + if (hasDouble) { + return doubleValue; + } else { + throw new UnexpectedResultException(value); + } + } + + @Override + public void executeVoid(VirtualFrame frame) { + } + + public void guard(VirtualFrame frame) throws UnexpectedResultException { + final RubyContext context = getContext(); + + final Object receiverObject = receiver.execute(frame); + + RubyBasicObject receiverRubyObject; + + // TODO(CS): put the boxing into a separate node that can specialize for each type it sees + + if (receiverObject instanceof RubyBasicObject) { + receiverRubyObject = (RubyBasicObject) receiverObject; + } else { + boxBranchProfile.enter(); + receiverRubyObject = context.getCoreLibrary().box(receiverObject); + } + + if (receiverRubyObject.getRubyClass() != expectedClass) { + CompilerDirectives.transferToInterpreter(); + throw new UnexpectedResultException(uninitialize(receiverRubyObject)); + } + + try { + unmodifiedAssumption.check(); + } catch (InvalidAssumptionException e) { + throw new UnexpectedResultException(uninitialize(receiverRubyObject)); + } + } + + private Object uninitialize(RubyBasicObject receiverObject) { + return replace(new UninitializedReadConstantNode(getContext(), getSourceSection(), name, receiver)).execute(receiverObject); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/constants/ReadConstantNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/constants/ReadConstantNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.constants; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; + +public abstract class ReadConstantNode extends RubyNode { + + protected final String name; + @Child protected RubyNode receiver; + + public ReadConstantNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver) { + super(context, sourceSection); + this.name = name; + this.receiver = adoptChild(receiver); + } + + @Override + public Object isDefined(VirtualFrame frame) { + final RubyContext context = getContext(); + + if (name.equals("Encoding")) { + /* + * Work-around so I don't have to load the iconv library - runners/formatters/junit.rb. + */ + return context.makeString("constant"); + } + + Object value; + + try { + value = context.getCoreLibrary().box(receiver.execute(frame)).getLookupNode().lookupConstant(name); + } catch (RaiseException e) { + /* + * If we are looking up a constant in a constant that is itself undefined, we return Nil + * rather than raising the error. Eg.. defined?(Defined::Undefined1::Undefined2) + */ + + if (e.getRubyException().getRubyClass() == context.getCoreLibrary().getNameErrorClass()) { + return NilPlaceholder.INSTANCE; + } + + throw e; + } + + if (value == null) { + return NilPlaceholder.INSTANCE; + } else { + return context.makeString("constant"); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/constants/UninitializedReadConstantNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/constants/UninitializedReadConstantNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.constants; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Represents an uninitialized constant read from some object. After the first read it will be + * specialized to some other node. This is the starting point for all constant reads. + */ +@NodeInfo(shortName = "uninitialized-read-constant") +public class UninitializedReadConstantNode extends ReadConstantNode { + + public UninitializedReadConstantNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver) { + super(context, sourceSection, name, receiver); + } + + /** + * This execute method allows us to pass in the already executed receiver object, so that during + * uninitialization it is not executed once by the specialized node and again by this node. + */ + public Object execute(RubyBasicObject receiverObject) { + CompilerAsserts.neverPartOfCompilation(); + + final RubyContext context = receiverObject.getRubyClass().getContext(); + + Object value; + + value = receiverObject.getLookupNode().lookupConstant(name); + + if (value == null && receiverObject instanceof RubyModule) { + /* + * FIXME(CS): I'm obviously doing something wrong with constant lookup in nested modules + * here, but explicitly looking in the Module itself, not its lookup node, seems to fix + * it for now. + */ + + value = ((RubyModule) receiverObject).lookupConstant(name); + } + + if (value == null) { + throw new RaiseException(context.getCoreLibrary().nameErrorUninitializedConstant(name)); + } + + replace(new CachedReadConstantNode(context, getSourceSection(), name, receiver, receiverObject.getRubyClass(), value)); + + assert RubyContext.shouldObjectBeVisible(value); + + return value; + } + + @Override + public Object execute(VirtualFrame frame) { + CompilerDirectives.transferToInterpreter(); + + final RubyContext context = getContext(); + + final Object receiverObject = receiver.execute(frame); + final RubyBasicObject receiverRubyObject = context.getCoreLibrary().box(receiverObject); + + return execute(receiverRubyObject); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/constants/WriteConstantNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/constants/WriteConstantNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.constants; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * Represents writing a constant into some module. + */ +@NodeInfo(shortName = "write-constant") +public class WriteConstantNode extends RubyNode { + + private final String name; + @Child protected RubyNode module; + @Child protected RubyNode rhs; + + public WriteConstantNode(RubyContext context, SourceSection sourceSection, String name, RubyNode module, RubyNode rhs) { + super(context, sourceSection); + this.name = name; + this.module = adoptChild(module); + this.rhs = adoptChild(rhs); + } + + @Override + public Object execute(VirtualFrame frame) { + // TODO(cs): can module ever not evaluate to a RubyModule? + + final RubyModule moduleObject = (RubyModule) module.execute(frame); + + final Object rhsValue = rhs.execute(frame); + + assert rhsValue != null; + assert !(rhsValue instanceof String); + + moduleObject.setModuleConstant(name, rhsValue); + + return rhsValue; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/AndNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/AndNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.control; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * Represents a Ruby {@code and} or {@code &&} expression. + */ +@NodeInfo(shortName = "and") +@NodeChildren({@NodeChild("left"), @NodeChild("right")}) +public abstract class AndNode extends RubyNode { + + public AndNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public AndNode(AndNode copy) { + super(copy.getContext(), copy.getSourceSection()); + } + + @ShortCircuit("right") + public boolean needsRightNode(Object a) { + return GeneralConversions.toBoolean(a); + } + + @ShortCircuit("right") + public boolean needsRightNode(boolean a) { + return a; + } + + @Specialization + public boolean doBoolean(boolean a, boolean hasB, boolean b) { + return hasB ? b : a; + } + + @Specialization + public Object doObject(boolean a, boolean hasB, Object b) { + return hasB ? b : a; + } + + @Generic + public Object doGeneric(Object a, boolean hasB, Object b) { + return hasB ? b : a; + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/BreakNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/BreakNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.control; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; + +@NodeInfo(shortName = "break") +public class BreakNode extends RubyNode { + + @Child private RubyNode child; + + public BreakNode(RubyContext context, SourceSection sourceSection, RubyNode child) { + super(context, sourceSection); + this.child = adoptChild(child); + } + + @Override + public Object execute(VirtualFrame frame) { + throw new BreakException(child.execute(frame)); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/ElidableResultNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/ElidableResultNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.control; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * This node has a pair of children - one required and one elidable result. The required node is + * always executed, but its result is discarded. Therefore it should perform some useful side + * effects. The elidable node is executed, and its result value returned, if an execute method with + * a non-void type is used. It is not executed at all if a void typed execute method is used. + * Therefore it should not perform any observable side effects. + */ +@NodeInfo(shortName = "elidable-result") +public class ElidableResultNode extends RubyNode { + + @Child protected RubyNode required; + @Child protected RubyNode elidableResult; + + public ElidableResultNode(RubyContext context, SourceSection sourceSection, RubyNode required, RubyNode elidableResult) { + super(context, sourceSection); + this.required = adoptChild(required); + this.elidableResult = adoptChild(elidableResult); + } + + @Override + public int executeFixnum(VirtualFrame frame) throws UnexpectedResultException { + required.executeVoid(frame); + return elidableResult.executeFixnum(frame); + } + + @Override + public double executeFloat(VirtualFrame frame) throws UnexpectedResultException { + required.executeVoid(frame); + return elidableResult.executeFloat(frame); + } + + @Override + public Object execute(VirtualFrame frame) { + required.executeVoid(frame); + return elidableResult.execute(frame); + } + + @Override + public void executeVoid(VirtualFrame frame) { + required.execute(frame); + } + + @Override + public Object isDefined(VirtualFrame frame) { + return elidableResult.isDefined(frame); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/EnsureNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/EnsureNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.control; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * Represents an ensure clause in exception handling. Represented separately to the try part. + */ +@NodeInfo(shortName = "ensure") +public class EnsureNode extends RubyNode { + + @Child protected RubyNode tryPart; + @Child protected RubyNode ensurePart; + + public EnsureNode(RubyContext context, SourceSection sourceSection, RubyNode tryPart, RubyNode ensurePart) { + super(context, sourceSection); + this.tryPart = adoptChild(tryPart); + this.ensurePart = adoptChild(ensurePart); + } + + @Override + public Object execute(VirtualFrame frame) { + try { + return tryPart.execute(frame); + } finally { + ensurePart.executeVoid(frame); + } + } + + @Override + public void executeVoid(VirtualFrame frame) { + try { + tryPart.executeVoid(frame); + } finally { + ensurePart.executeVoid(frame); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/FlipFlopNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/FlipFlopNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.control; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.nodes.cast.*; +import com.oracle.truffle.ruby.nodes.methods.locals.*; +import com.oracle.truffle.ruby.runtime.*; + +@NodeInfo(shortName = "flip-flop") +public class FlipFlopNode extends RubyNode { + + @Child protected BooleanCastNode begin; + @Child protected BooleanCastNode end; + @Child protected FlipFlopStateNode stateNode; + + private final boolean exclusive; + + public FlipFlopNode(RubyContext context, SourceSection sourceSection, BooleanCastNode begin, BooleanCastNode end, FlipFlopStateNode stateNode, boolean exclusive) { + super(context, sourceSection); + this.begin = adoptChild(begin); + this.end = adoptChild(end); + this.stateNode = adoptChild(stateNode); + this.exclusive = exclusive; + } + + @Override + public boolean executeBoolean(VirtualFrame frame) { + if (exclusive) { + if (stateNode.getState(frame)) { + if (end.executeBoolean(frame)) { + stateNode.setState(frame, false); + } + + return true; + } else { + final boolean newState = begin.executeBoolean(frame); + stateNode.setState(frame, newState); + return newState; + } + } else { + if (stateNode.getState(frame)) { + if (end.executeBoolean(frame)) { + stateNode.setState(frame, false); + } + + return true; + } else { + if (begin.executeBoolean(frame)) { + stateNode.setState(frame, !end.executeBoolean(frame)); + return true; + } + + return false; + } + } + } + + @Override + public Object execute(VirtualFrame frame) { + return executeBoolean(frame); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/IfNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/IfNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.control; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.utilities.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.nodes.cast.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * Represents a Ruby {@code if} expression. Note that in this representation we always have an + * {@code else} part. + */ +@NodeInfo(shortName = "if") +public class IfNode extends RubyNode { + + @Child protected BooleanCastNode condition; + @Child protected RubyNode thenBody; + @Child protected RubyNode elseBody; + + private final BranchProfile thenProfile = new BranchProfile(); + private final BranchProfile elseProfile = new BranchProfile(); + + public IfNode(RubyContext context, SourceSection sourceSection, BooleanCastNode condition, RubyNode thenBody, RubyNode elseBody) { + super(context, sourceSection); + this.condition = adoptChild(condition); + this.thenBody = adoptChild(thenBody); + this.elseBody = adoptChild(elseBody); + } + + @Override + public Object execute(VirtualFrame frame) { + if (condition.executeBoolean(frame)) { + thenProfile.enter(); + return thenBody.execute(frame); + } else { + elseProfile.enter(); + return elseBody.execute(frame); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/NextNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/NextNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.control; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; + +@NodeInfo(shortName = "next") +public class NextNode extends RubyNode { + + public NextNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + @Override + public Object execute(VirtualFrame frame) { + throw new NextException(); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/NotNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/NotNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.control; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.nodes.cast.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * Represents a Ruby {@code not} or {@code !} expression. + */ +@NodeInfo(shortName = "not") +public class NotNode extends RubyNode { + + @Child protected BooleanCastNode child; + + public NotNode(RubyContext context, SourceSection sourceSection, BooleanCastNode child) { + super(context, sourceSection); + this.child = adoptChild(child); + } + + @Override + public boolean executeBoolean(VirtualFrame frame) { + return !child.executeBoolean(frame); + } + + @Override + public Object execute(VirtualFrame frame) { + return executeBoolean(frame); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/OrNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/OrNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.control; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * Represents a Ruby {@code or} or {@code ||} expression. + */ +@NodeInfo(shortName = "or") +@NodeChildren({@NodeChild("left"), @NodeChild("right")}) +public abstract class OrNode extends RubyNode { + + public OrNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public OrNode(OrNode copy) { + super(copy.getContext(), copy.getSourceSection()); + } + + @ShortCircuit("right") + public boolean needsRightNode(Object a) { + return !GeneralConversions.toBoolean(a); + } + + @ShortCircuit("right") + public boolean needsRightNode(boolean a) { + return !a; + } + + @Specialization + public Object doBoolean(boolean a, boolean hasB, Object b) { + return hasB ? b : a; + } + + @Generic + public Object doGeneric(Object a, boolean hasB, Object b) { + return hasB ? b : a; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/RedoNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/RedoNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.control; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; + +@NodeInfo(shortName = "redo") +public class RedoNode extends RubyNode { + + public RedoNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + @Override + public Object execute(VirtualFrame frame) { + throw new RedoException(); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/RescueAnyNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/RescueAnyNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.control; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Rescues any exception. + */ +@NodeInfo(shortName = "rescue-any") +public class RescueAnyNode extends RescueNode { + + public RescueAnyNode(RubyContext context, SourceSection sourceSection, RubyNode body) { + super(context, sourceSection, body); + } + + @Override + public boolean canHandle(VirtualFrame frame, RubyBasicObject exception) { + return true; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/RescueClassesNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/RescueClassesNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.control; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Rescues any of a set of classes. + */ +@NodeInfo(shortName = "rescue-classes") +public class RescueClassesNode extends RescueNode { + + @Children final RubyNode[] handlingClassNodes; + + public RescueClassesNode(RubyContext context, SourceSection sourceSection, RubyNode[] handlingClassNodes, RubyNode body) { + super(context, sourceSection, body); + this.handlingClassNodes = adoptChildren(handlingClassNodes); + } + + @ExplodeLoop + @Override + public boolean canHandle(VirtualFrame frame, RubyBasicObject exception) { + final RubyClass exceptionRubyClass = exception.getRubyClass(); + + for (RubyNode handlingClassNode : handlingClassNodes) { + // TODO(CS): what if we don't get a class? + + final RubyClass handlingClass = (RubyClass) handlingClassNode.execute(frame); + + if (exceptionRubyClass.assignableTo(handlingClass)) { + return true; + } + } + + return false; + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/RescueNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/RescueNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.control; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Base node for all nodes which may be able to rescue an exception. They have a test method + * {@link #canHandle} and a body to execute if that test passes. + */ +public abstract class RescueNode extends RubyNode { + + @Child protected RubyNode body; + + public RescueNode(RubyContext context, SourceSection sourceSection, RubyNode body) { + super(context, sourceSection); + this.body = adoptChild(body); + } + + public abstract boolean canHandle(VirtualFrame frame, RubyBasicObject exception); + + @Override + public Object execute(VirtualFrame frame) { + return body.execute(frame); + } + + @Override + public void executeVoid(VirtualFrame frame) { + body.executeVoid(frame); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/RescueSplatNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/RescueSplatNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.control; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Rescue any of several classes, that we get from an expression that evaluates to an array of + * classes. + * + */ +@NodeInfo(shortName = "rescue-splat") +public class RescueSplatNode extends RescueNode { + + @Child RubyNode handlingClassesArray; + + public RescueSplatNode(RubyContext context, SourceSection sourceSection, RubyNode handlingClassesArray, RubyNode body) { + super(context, sourceSection, body); + this.handlingClassesArray = adoptChild(handlingClassesArray); + } + + @ExplodeLoop + @Override + public boolean canHandle(VirtualFrame frame, RubyBasicObject exception) { + final RubyArray handlingClasses = (RubyArray) handlingClassesArray.execute(frame); + + final RubyClass exceptionRubyClass = exception.getRubyClass(); + + for (Object handlingClass : handlingClasses.asList()) { + if (exceptionRubyClass.assignableTo((RubyClass) handlingClass)) { + return true; + } + } + + return false; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/RetryNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/RetryNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.control; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; + +@NodeInfo(shortName = "retry") +public class RetryNode extends RubyNode { + + public RetryNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + @Override + public Object execute(VirtualFrame frame) { + throw new RetryException(); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/ReturnNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/ReturnNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.control; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; + +/** + * Represents an explicit return. The return ID indicates where we should be returning to - this can + * be non-trivial if you have blocks. + */ +@NodeInfo(shortName = "return") +public class ReturnNode extends RubyNode { + + private final long returnID; + @Child protected RubyNode value; + + public ReturnNode(RubyContext context, SourceSection sourceSection, long returnID, RubyNode value) { + super(context, sourceSection); + this.returnID = returnID; + this.value = adoptChild(value); + } + + @Override + public Object execute(VirtualFrame frame) { + throw new ReturnException(returnID, value.execute(frame)); + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/SequenceNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/SequenceNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.control; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * A sequence of statements to be executed in serial. + */ +@NodeInfo(shortName = "sequence") +public final class SequenceNode extends RubyNode { + + @Children protected final RubyNode[] body; + + public SequenceNode(RubyContext context, SourceSection sourceSection, RubyNode... body) { + super(context, sourceSection); + this.body = adoptChildren(body); + } + + @ExplodeLoop + @Override + public Object execute(VirtualFrame frame) { + for (int n = 0; n < body.length - 1; n++) { + body[n].executeVoid(frame); + } + + return body[body.length - 1].execute(frame); + } + + @ExplodeLoop + @Override + public void executeVoid(VirtualFrame frame) { + for (int n = 0; n < body.length; n++) { + body[n].executeVoid(frame); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/TryNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/TryNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.control; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.utilities.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Represents a block of code run with exception handlers. There's no {@code try} keyword in Ruby - + * it's implicit - but it's similar to a try statement in any other language. + */ +@NodeInfo(shortName = "try") +public class TryNode extends RubyNode { + + @Child protected RubyNode tryPart; + @Children final RescueNode[] rescueParts; + @Child protected RubyNode elsePart; + + private final BranchProfile controlFlowProfile = new BranchProfile(); + + public TryNode(RubyContext context, SourceSection sourceSection, RubyNode tryPart, RescueNode[] rescueParts, RubyNode elsePart) { + super(context, sourceSection); + this.tryPart = adoptChild(tryPart); + this.rescueParts = adoptChildren(rescueParts); + this.elsePart = adoptChild(elsePart); + } + + @Override + public Object execute(VirtualFrame frame) { + while (true) { + try { + final Object result = tryPart.execute(frame); + elsePart.executeVoid(frame); + return result; + } catch (ControlFlowException exception) { + controlFlowProfile.enter(); + + throw exception; + } catch (RuntimeException exception) { + CompilerDirectives.transferToInterpreter(); + + try { + return handleException(frame, exception); + } catch (RetryException e) { + continue; + } + } + } + } + + private Object handleException(VirtualFrame frame, RuntimeException exception) { + CompilerAsserts.neverPartOfCompilation(); + + final RubyContext context = getContext(); + + final RubyBasicObject rubyException = ExceptionTranslator.translateException(context, exception); + + context.getCoreLibrary().getGlobalVariablesObject().setInstanceVariable("$!", rubyException); + + for (RescueNode rescue : rescueParts) { + if (rescue.canHandle(frame, rubyException)) { + return rescue.execute(frame); + } + } + + throw exception; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/WhileNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/control/WhileNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.control; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.utilities.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.nodes.cast.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; + +/** + * Represents a Ruby {@code while} statement. + */ +@NodeInfo(shortName = "while") +public class WhileNode extends RubyNode { + + @Child protected BooleanCastNode condition; + @Child protected RubyNode body; + + private final BranchProfile breakProfile = new BranchProfile(); + private final BranchProfile nextProfile = new BranchProfile(); + private final BranchProfile redoProfile = new BranchProfile(); + + public WhileNode(RubyContext context, SourceSection sourceSection, BooleanCastNode condition, RubyNode body) { + super(context, sourceSection); + this.condition = adoptChild(condition); + this.body = adoptChild(body); + } + + @Override + public Object execute(VirtualFrame frame) { + outer: while (condition.executeBoolean(frame)) { + while (true) { + try { + body.execute(frame); + continue outer; + } catch (BreakException e) { + breakProfile.enter(); + return e.getResult(); + } catch (NextException e) { + nextProfile.enter(); + continue outer; + } catch (RedoException e) { + redoProfile.enter(); + } + } + } + + return NilPlaceholder.INSTANCE; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ArrayConcatNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ArrayConcatNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +/** + * Concatenate arrays. + */ +@NodeInfo(shortName = "array-concat") +public final class ArrayConcatNode extends RubyNode { + + @Children protected final RubyNode[] children; + + public ArrayConcatNode(RubyContext context, SourceSection sourceSection, RubyNode[] children) { + super(context, sourceSection); + assert children.length > 1; + this.children = adoptChildren(children); + } + + @ExplodeLoop + @Override + public Object execute(VirtualFrame frame) { + final RubyArray array = new RubyArray(getContext().getCoreLibrary().getArrayClass()); + + for (int n = 0; n < children.length; n++) { + final Object childObject = children[n].execute(frame); + + if (childObject instanceof RubyArray) { + // setRangeArray has special cases for setting a zero-length range at the end + final int end = array.size(); + array.setRangeArrayExclusive(end, end, (RubyArray) childObject); + } else { + array.push(childObject); + } + } + + return array; + } + + @ExplodeLoop + @Override + public void executeVoid(VirtualFrame frame) { + for (int n = 0; n < children.length; n++) { + children[n].executeVoid(frame); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ArrayCoreMethodNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ArrayCoreMethodNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +public abstract class ArrayCoreMethodNode extends CoreMethodNode { + + public ArrayCoreMethodNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ArrayCoreMethodNode(ArrayCoreMethodNode prev) { + super(prev); + } + + protected boolean isEmptyStore(RubyArray receiver) { + return receiver.getArrayStore() instanceof EmptyArrayStore; + } + + protected boolean isFixnumStore(RubyArray receiver) { + return receiver.getArrayStore() instanceof FixnumArrayStore; + } + + protected boolean isFixnumImmutablePairStore(RubyArray receiver) { + return receiver.getArrayStore() instanceof FixnumImmutablePairArrayStore; + } + + protected boolean isObjectStore(RubyArray receiver) { + return receiver.getArrayStore() instanceof ObjectArrayStore; + } + + protected boolean isObjectImmutablePairStore(RubyArray receiver) { + return receiver.getArrayStore() instanceof ObjectImmutablePairArrayStore; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ArrayIndexNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ArrayIndexNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +/** + * Index an array, without using any method lookup. This isn't a call - it's an operation on a core + * class. + */ +@NodeInfo(shortName = "array-index") +@NodeChildren({@NodeChild(value = "array", type = RubyNode.class)}) +public abstract class ArrayIndexNode extends RubyNode { + + final int index; + + public ArrayIndexNode(RubyContext context, SourceSection sourceSection, int index) { + super(context, sourceSection); + this.index = index; + } + + public ArrayIndexNode(ArrayIndexNode prev) { + super(prev); + index = prev.index; + } + + @Specialization(guards = "isEmptyStore", order = 1) + public NilPlaceholder indexEmpty(@SuppressWarnings("unused") RubyArray array) { + return NilPlaceholder.INSTANCE; + } + + @Specialization(guards = "isFixnumStore", rewriteOn = UnexpectedResultException.class, order = 2) + public int indexFixnum(RubyArray array) throws UnexpectedResultException { + final FixnumArrayStore store = (FixnumArrayStore) array.getArrayStore(); + return store.getFixnum(ArrayUtilities.normaliseIndex(store.size(), index)); + } + + @Specialization(guards = "isFixnumStore", order = 3) + public Object indexMaybeFixnum(RubyArray array) { + final FixnumArrayStore store = (FixnumArrayStore) array.getArrayStore(); + + try { + return store.getFixnum(ArrayUtilities.normaliseIndex(store.size(), index)); + } catch (UnexpectedResultException e) { + return e.getResult(); + } + } + + @Specialization(guards = "isFixnumImmutablePairStore", rewriteOn = UnexpectedResultException.class, order = 4) + public int indexFixnumImmutablePair(RubyArray array) throws UnexpectedResultException { + final FixnumImmutablePairArrayStore store = (FixnumImmutablePairArrayStore) array.getArrayStore(); + return store.getFixnum(ArrayUtilities.normaliseIndex(store.size(), index)); + } + + @Specialization(guards = "isFixnumImmutablePairStore", order = 5) + public Object indexMaybeFixnumImmutablePair(RubyArray array) { + final FixnumImmutablePairArrayStore store = (FixnumImmutablePairArrayStore) array.getArrayStore(); + + try { + return store.getFixnum(ArrayUtilities.normaliseIndex(store.size(), index)); + } catch (UnexpectedResultException e) { + return e.getResult(); + } + } + + @Specialization(guards = "isObjectStore", order = 6) + public Object indexObject(RubyArray array) { + final ObjectArrayStore store = (ObjectArrayStore) array.getArrayStore(); + return store.get(ArrayUtilities.normaliseIndex(store.size(), index)); + } + + @Specialization(guards = "isObjectImmutablePairStore", order = 7) + public Object indexObjectImmutablePair(RubyArray array) { + final ObjectImmutablePairArrayStore store = (ObjectImmutablePairArrayStore) array.getArrayStore(); + return store.get(ArrayUtilities.normaliseIndex(store.size(), index)); + } + + protected boolean isEmptyStore(RubyArray receiver) { + return receiver.getArrayStore() instanceof EmptyArrayStore; + } + + protected boolean isFixnumStore(RubyArray receiver) { + return receiver.getArrayStore() instanceof FixnumArrayStore; + } + + protected boolean isFixnumImmutablePairStore(RubyArray receiver) { + return receiver.getArrayStore() instanceof FixnumImmutablePairArrayStore; + } + + protected boolean isObjectStore(RubyArray receiver) { + return receiver.getArrayStore() instanceof ObjectArrayStore; + } + + protected boolean isObjectImmutablePairStore(RubyArray receiver) { + return receiver.getArrayStore() instanceof ObjectImmutablePairArrayStore; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ArrayNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ArrayNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,1066 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import java.util.*; + +import com.oracle.truffle.api.CompilerDirectives.SlowPath; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; +import com.oracle.truffle.ruby.runtime.core.range.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +@CoreClass(name = "Array") +public abstract class ArrayNodes { + + @CoreMethod(names = "+", minArgs = 1, maxArgs = 1) + public abstract static class AddNode extends CoreMethodNode { + + public AddNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public AddNode(AddNode prev) { + super(prev); + } + + @Specialization + public RubyArray equal(RubyArray a, RubyArray b) { + final RubyArray result = new RubyArray(getContext().getCoreLibrary().getArrayClass()); + result.setRangeArrayExclusive(0, 0, a); + result.setRangeArrayExclusive(a.size(), a.size(), b); + return result; + } + + } + + @CoreMethod(names = "-", minArgs = 1, maxArgs = 1) + public abstract static class SubNode extends CoreMethodNode { + + public SubNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SubNode(SubNode prev) { + super(prev); + } + + @Specialization + public RubyArray equal(RubyArray a, RubyArray b) { + return a.relativeComplement(b); + } + + } + + @CoreMethod(names = "*", minArgs = 1, maxArgs = 1) + public abstract static class MulNode extends CoreMethodNode { + + public MulNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public MulNode(MulNode prev) { + super(prev); + } + + @Specialization + public RubyArray mul(RubyArray array, int count) { + // TODO(CS): use the same storage type + + final RubyArray result = new RubyArray(array.getRubyClass().getContext().getCoreLibrary().getArrayClass()); + + for (int n = 0; n < count; n++) { + for (int i = 0; i < array.size(); i++) { + result.push(array.get(i)); + } + } + + return result; + } + + } + + @CoreMethod(names = "==", minArgs = 1, maxArgs = 1) + public abstract static class EqualNode extends CoreMethodNode { + + public EqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EqualNode(EqualNode prev) { + super(prev); + } + + @Specialization + public boolean equal(RubyArray a, RubyArray b) { + // TODO(CS) + return a.equals(b); + } + + } + + @CoreMethod(names = "[]", minArgs = 1, maxArgs = 2) + public abstract static class IndexNode extends ArrayCoreMethodNode { + + public IndexNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public IndexNode(IndexNode prev) { + super(prev); + } + + @Specialization(guards = "isEmptyStore", order = 1) + public NilPlaceholder indexEmpty(@SuppressWarnings("unused") RubyArray array, @SuppressWarnings("unused") int index, @SuppressWarnings("unused") UndefinedPlaceholder unused) { + return NilPlaceholder.INSTANCE; + } + + @Specialization(guards = "isFixnumStore", rewriteOn = UnexpectedResultException.class, order = 2) + public int indexFixnum(RubyArray array, int index, @SuppressWarnings("unused") UndefinedPlaceholder unused) throws UnexpectedResultException { + final FixnumArrayStore store = (FixnumArrayStore) array.getArrayStore(); + return store.getFixnum(ArrayUtilities.normaliseIndex(store.size(), index)); + } + + @Specialization(guards = "isFixnumStore", order = 3) + public Object indexMaybeFixnum(RubyArray array, int index, @SuppressWarnings("unused") UndefinedPlaceholder unused) { + final FixnumArrayStore store = (FixnumArrayStore) array.getArrayStore(); + + try { + return store.getFixnum(ArrayUtilities.normaliseIndex(store.size(), index)); + } catch (UnexpectedResultException e) { + return e.getResult(); + } + } + + @Specialization(guards = "isFixnumImmutablePairStore", rewriteOn = UnexpectedResultException.class, order = 4) + public int indexFixnumImmutablePair(RubyArray array, int index, @SuppressWarnings("unused") UndefinedPlaceholder unused) throws UnexpectedResultException { + final FixnumImmutablePairArrayStore store = (FixnumImmutablePairArrayStore) array.getArrayStore(); + return store.getFixnum(ArrayUtilities.normaliseIndex(store.size(), index)); + } + + @Specialization(guards = "isFixnumImmutablePairStore", order = 5) + public Object indexMaybeFixnumImmutablePair(RubyArray array, int index, @SuppressWarnings("unused") UndefinedPlaceholder unused) { + final FixnumImmutablePairArrayStore store = (FixnumImmutablePairArrayStore) array.getArrayStore(); + + try { + return store.getFixnum(ArrayUtilities.normaliseIndex(store.size(), index)); + } catch (UnexpectedResultException e) { + return e.getResult(); + } + } + + @Specialization(guards = "isObjectStore", order = 6) + public Object indexObject(RubyArray array, int index, @SuppressWarnings("unused") UndefinedPlaceholder unused) { + final ObjectArrayStore store = (ObjectArrayStore) array.getArrayStore(); + return store.get(ArrayUtilities.normaliseIndex(store.size(), index)); + } + + @Specialization(guards = "isObjectImmutablePairStore", order = 7) + public Object indexObjectImmutablePair(RubyArray array, int index, @SuppressWarnings("unused") UndefinedPlaceholder unused) { + final ObjectImmutablePairArrayStore store = (ObjectImmutablePairArrayStore) array.getArrayStore(); + return store.get(ArrayUtilities.normaliseIndex(store.size(), index)); + } + + @Specialization(order = 8) + public Object indexRange(RubyArray array, int begin, int rangeLength) { + final int length = array.size(); + final int normalisedBegin = ArrayUtilities.normaliseIndex(length, begin); + return array.getRangeExclusive(normalisedBegin, normalisedBegin + rangeLength); + } + + @Specialization(order = 9) + public Object indexRange(RubyArray array, FixnumRange range, @SuppressWarnings("unused") UndefinedPlaceholder unused) { + if (range.doesExcludeEnd()) { + return array.getRangeExclusive(range.getBegin(), range.getExclusiveEnd()); + } else { + return array.getRangeInclusive(range.getBegin(), range.getInclusiveEnd()); + } + } + + } + + @CoreMethod(names = "[]=", minArgs = 2, maxArgs = 3) + public abstract static class IndexSetNode extends ArrayCoreMethodNode { + + public IndexSetNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public IndexSetNode(IndexSetNode prev) { + super(prev); + } + + @Specialization(guards = "isEmptyStore", order = 1) + public Object indexSetEmpty(RubyArray array, int index, Object value, @SuppressWarnings("unused") UndefinedPlaceholder unused) { + array.set(index, value); + return value; + } + + @Specialization(guards = "isFixnumStore", rewriteOn = GeneraliseArrayStoreException.class, order = 2) + public int indexSetFixnum(RubyArray array, int index, int value, @SuppressWarnings("unused") UndefinedPlaceholder unused) throws GeneraliseArrayStoreException { + final FixnumArrayStore store = (FixnumArrayStore) array.getArrayStore(); + final int normalisedIndex = ArrayUtilities.normaliseIndex(store.size(), index); + store.setFixnum(normalisedIndex, value); + return value; + } + + @Specialization(guards = "isFixnumStore", order = 3) + public int indexSetFixnumMayGeneralise(RubyArray array, int index, int value, @SuppressWarnings("unused") UndefinedPlaceholder unused) { + final FixnumArrayStore store = (FixnumArrayStore) array.getArrayStore(); + final int normalisedIndex = ArrayUtilities.normaliseIndex(store.size(), index); + + try { + store.setFixnum(normalisedIndex, value); + } catch (GeneraliseArrayStoreException e) { + array.set(normalisedIndex, value); + } + + return value; + } + + @Specialization(guards = "isObjectStore", order = 4) + public Object indexSetObject(RubyArray array, int index, Object value, @SuppressWarnings("unused") UndefinedPlaceholder unused) { + final ObjectArrayStore store = (ObjectArrayStore) array.getArrayStore(); + final int normalisedIndex = ArrayUtilities.normaliseIndex(store.size(), index); + + try { + store.set(normalisedIndex, value); + } catch (GeneraliseArrayStoreException e) { + array.set(normalisedIndex, value); + } + + return value; + } + + @Specialization(order = 5) + public RubyArray indexSetRange(RubyArray array, FixnumRange range, RubyArray value, @SuppressWarnings("unused") UndefinedPlaceholder unused) { + if (range.doesExcludeEnd()) { + array.setRangeArrayExclusive(range.getBegin(), range.getExclusiveEnd(), value); + } else { + array.setRangeArrayInclusive(range.getBegin(), range.getInclusiveEnd(), value); + } + + return value; + } + + @Specialization(order = 6) + public Object indexSetRange(RubyArray array, FixnumRange range, Object value, @SuppressWarnings("unused") UndefinedPlaceholder unused) { + if (range.doesExcludeEnd()) { + array.setRangeSingleExclusive(range.getBegin(), range.getExclusiveEnd(), value); + } else { + array.setRangeSingleInclusive(range.getBegin(), range.getInclusiveEnd(), value); + } + + return value; + } + + @Specialization(order = 7) + public RubyArray indexSetRange(RubyArray array, int begin, int rangeLength, RubyArray value) { + array.setRangeArrayExclusive(begin, begin + rangeLength, value); + return value; + } + + @Specialization(order = 8) + public Object indexSetRange(RubyArray array, int begin, int rangeLength, Object value) { + if (value instanceof UndefinedPlaceholder) { + if (array.getArrayStore() instanceof EmptyArrayStore) { + return indexSetEmpty(array, begin, rangeLength, UndefinedPlaceholder.INSTANCE); + } else if (array.getArrayStore() instanceof FixnumArrayStore) { + return indexSetFixnumMayGeneralise(array, begin, rangeLength, UndefinedPlaceholder.INSTANCE); + } else { + return indexSetObject(array, begin, rangeLength, UndefinedPlaceholder.INSTANCE); + } + } + + array.setRangeSingleExclusive(begin, begin + rangeLength, value); + return value; + } + + } + + @CoreMethod(names = "all?", needsBlock = true, maxArgs = 0) + public abstract static class AllNode extends YieldingCoreMethodNode { + + public AllNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public AllNode(AllNode prev) { + super(prev); + } + + @Specialization + public boolean all(VirtualFrame frame, RubyArray array, RubyProc block) { + for (Object value : array.asList()) { + if (!yieldBoolean(frame, block, value)) { + return false; + } + } + + return true; + } + + } + + @CoreMethod(names = "any?", needsBlock = true, maxArgs = 0) + public abstract static class AnyNode extends YieldingCoreMethodNode { + + public AnyNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public AnyNode(AnyNode prev) { + super(prev); + } + + @Specialization + public boolean any(VirtualFrame frame, RubyArray array, RubyProc block) { + for (Object value : array.asList()) { + if (yieldBoolean(frame, block, value)) { + return true; + } + } + + return false; + } + + } + + @CoreMethod(names = "compact", maxArgs = 0) + public abstract static class CompactNode extends ArrayCoreMethodNode { + + public CompactNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public CompactNode(CompactNode prev) { + super(prev); + } + + @Specialization + public RubyArray compat(RubyArray array) { + final RubyArray result = new RubyArray(array.getRubyClass().getContext().getCoreLibrary().getArrayClass()); + + for (Object value : array.asList()) { + if (!(value instanceof NilPlaceholder || value instanceof RubyNilClass)) { + result.push(value); + } + } + + return result; + } + + } + + @CoreMethod(names = "concat", minArgs = 1, maxArgs = 1) + public abstract static class ConcatNode extends CoreMethodNode { + + public ConcatNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ConcatNode(ConcatNode prev) { + super(prev); + } + + @Specialization + public RubyArray concat(RubyArray array, RubyArray other) { + array.setRangeArrayExclusive(array.size(), array.size(), other); + return array; + } + + } + + @CoreMethod(names = "delete", minArgs = 1, maxArgs = 1) + public abstract static class DeleteNode extends CoreMethodNode { + + public DeleteNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public DeleteNode(DeleteNode prev) { + super(prev); + } + + @Specialization + public Object delete(RubyArray array, Object value) { + boolean deleted = false; + int n = 0; + + while (n < array.size()) { + if (array.get(n) == value) { + array.deleteAt(n); + deleted = true; + } else { + n++; + } + } + + if (deleted) { + return value; + } else { + return NilPlaceholder.INSTANCE; + } + } + + } + + @CoreMethod(names = "delete_at", minArgs = 1, maxArgs = 1) + public abstract static class DeleteAtNode extends CoreMethodNode { + + public DeleteAtNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public DeleteAtNode(DeleteAtNode prev) { + super(prev); + } + + @Specialization + public Object deleteAt(RubyArray array, int index) { + return array.deleteAt(index); + } + + } + + @CoreMethod(names = "dup", maxArgs = 0) + public abstract static class DupNode extends ArrayCoreMethodNode { + + public DupNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public DupNode(DupNode prev) { + super(prev); + } + + @Specialization + public Object dup(RubyArray array) { + return array.dup(); + } + + } + + @CoreMethod(names = "each", needsBlock = true, maxArgs = 0) + public abstract static class EachNode extends YieldingCoreMethodNode { + + public EachNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EachNode(EachNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder each(VirtualFrame frame, RubyArray array, RubyProc block) { + for (int n = 0; n < array.size(); n++) { + try { + yield(frame, block, array.get(n)); + } catch (BreakException e) { + break; + } + } + + return NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = "each_with_index", needsBlock = true, maxArgs = 0) + public abstract static class EachWithIndexNode extends YieldingCoreMethodNode { + + public EachWithIndexNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EachWithIndexNode(EachWithIndexNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder eachWithIndex(VirtualFrame frame, RubyArray array, RubyProc block) { + for (int n = 0; n < array.size(); n++) { + try { + yield(frame, block, array.get(n), n); + } catch (BreakException e) { + break; + } + } + + return NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = "empty?", maxArgs = 0) + public abstract static class EmptyNode extends ArrayCoreMethodNode { + + public EmptyNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EmptyNode(EmptyNode prev) { + super(prev); + } + + @Specialization + public boolean isEmpty(RubyArray array) { + return array.isEmpty(); + } + + } + + @CoreMethod(names = "find", needsBlock = true, maxArgs = 0) + public abstract static class FindNode extends YieldingCoreMethodNode { + + public FindNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public FindNode(FindNode prev) { + super(prev); + } + + @Specialization + public Object find(VirtualFrame frame, RubyArray array, RubyProc block) { + for (int n = 0; n < array.size(); n++) { + try { + final Object value = array.get(n); + + if (yieldBoolean(frame, block, value)) { + return value; + } + } catch (BreakException e) { + break; + } + } + + return NilPlaceholder.INSTANCE; + } + } + + @CoreMethod(names = "first", maxArgs = 0) + public abstract static class FirstNode extends ArrayCoreMethodNode { + + public FirstNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public FirstNode(FirstNode prev) { + super(prev); + } + + @Specialization + public Object first(RubyArray array) { + if (array.size() == 0) { + return NilPlaceholder.INSTANCE; + } else { + return array.get(0); + } + } + + } + + @CoreMethod(names = "flatten", maxArgs = 0) + public abstract static class FlattenNode extends ArrayCoreMethodNode { + + public FlattenNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public FlattenNode(FlattenNode prev) { + super(prev); + } + + @Specialization + public RubyArray flatten(RubyArray array) { + final RubyArray result = new RubyArray(array.getRubyClass().getContext().getCoreLibrary().getArrayClass()); + array.flattenTo(result); + return result; + } + + } + + @CoreMethod(names = "include?", minArgs = 1, maxArgs = 1) + public abstract static class IncludeNode extends ArrayCoreMethodNode { + + public IncludeNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public IncludeNode(IncludeNode prev) { + super(prev); + } + + @Specialization + public boolean include(RubyArray array, Object value) { + return array.contains(value); + } + + } + + @CoreMethod(names = {"inject", "reduce"}, needsBlock = true, minArgs = 0, maxArgs = 1) + public abstract static class InjectNode extends YieldingCoreMethodNode { + + public InjectNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InjectNode(InjectNode prev) { + super(prev); + } + + @Specialization + public Object inject(VirtualFrame frame, RubyArray array, @SuppressWarnings("unused") UndefinedPlaceholder initial, RubyProc block) { + Object accumulator = array.get(0); + + for (int n = 1; n < array.size(); n++) { + accumulator = yield(frame, block, accumulator, array.get(n)); + } + + return accumulator; + } + + @Specialization + public Object inject(VirtualFrame frame, RubyArray array, Object initial, RubyProc block) { + if (initial instanceof UndefinedPlaceholder) { + return inject(frame, array, UndefinedPlaceholder.INSTANCE, block); + } + + Object accumulator = initial; + + for (int n = 0; n < array.size(); n++) { + accumulator = yield(frame, block, accumulator, array.get(n)); + } + + return accumulator; + } + + } + + @CoreMethod(names = "insert", minArgs = 2, maxArgs = 2) + public abstract static class InsertNode extends ArrayCoreMethodNode { + + public InsertNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InsertNode(InsertNode prev) { + super(prev); + } + + @Specialization(guards = "isFixnumStore", rewriteOn = GeneraliseArrayStoreException.class) + public int insert(RubyArray array, int index, int value) throws GeneraliseArrayStoreException { + final FixnumArrayStore store = (FixnumArrayStore) array.getArrayStore(); + store.insertFixnum(ArrayUtilities.normaliseIndex(store.size(), index), value); + return value; + } + + @Specialization + public Object insert(RubyArray array, int index, Object value) { + array.insert(ArrayUtilities.normaliseIndex(array.size(), index), value); + return value; + } + + } + + @CoreMethod(names = {"inspect", "to_s"}, maxArgs = 0) + public abstract static class InspectNode extends CoreMethodNode { + + public InspectNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InspectNode(InspectNode prev) { + super(prev); + } + + @Specialization + public RubyString inspect(RubyArray array) { + final RubyContext context = getContext(); + return getContext().makeString(inspect(context, array)); + } + + @SlowPath + private static String inspect(RubyContext context, RubyArray array) { + final StringBuilder builder = new StringBuilder(); + + builder.append("["); + + for (int n = 0; n < array.size(); n++) { + if (n > 0) { + builder.append(", "); + } + + // TODO(CS): slow path send + builder.append(context.getCoreLibrary().box(array.get(n)).send("inspect", null)); + } + + builder.append("]"); + + return builder.toString(); + } + + } + + @CoreMethod(names = "join", minArgs = 1, maxArgs = 1) + public abstract static class JoinNode extends ArrayCoreMethodNode { + + public JoinNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public JoinNode(JoinNode prev) { + super(prev); + } + + @Specialization + public RubyString join(RubyArray array, RubyString separator) { + return array.getRubyClass().getContext().makeString(array.join(separator.toString())); + } + + } + + @CoreMethod(names = "last", maxArgs = 0) + public abstract static class LastNode extends ArrayCoreMethodNode { + + public LastNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public LastNode(LastNode prev) { + super(prev); + } + + @Specialization + public Object last(RubyArray array) { + final int size = array.size(); + if (size == 0) { + return NilPlaceholder.INSTANCE; + } else { + return array.get(size - 1); + } + } + + } + + @CoreMethod(names = {"map", "collect"}, needsBlock = true, maxArgs = 0) + public abstract static class MapNode extends YieldingCoreMethodNode { + + public MapNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public MapNode(MapNode prev) { + super(prev); + } + + @Specialization + public RubyArray map(VirtualFrame frame, RubyArray array, RubyProc block) { + final RubyArray result = new RubyArray(array.getRubyClass().getContext().getCoreLibrary().getArrayClass()); + + for (int n = 0; n < array.size(); n++) { + result.push(yield(frame, block, array.get(n))); + } + + return result; + } + } + + @CoreMethod(names = {"map!", "collect!"}, needsBlock = true, maxArgs = 0) + public abstract static class MapInPlaceNode extends YieldingCoreMethodNode { + + public MapInPlaceNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public MapInPlaceNode(MapInPlaceNode prev) { + super(prev); + } + + @Specialization + public RubyArray mapInPlace(VirtualFrame frame, RubyArray array, RubyProc block) { + for (int n = 0; n < array.size(); n++) { + array.set(n, yield(frame, block, array.get(n))); + } + + return array; + } + } + + @CoreMethod(names = "pop", maxArgs = 0) + public abstract static class PopNode extends ArrayCoreMethodNode { + + public PopNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public PopNode(PopNode prev) { + super(prev); + } + + @Specialization + public Object pop(RubyArray array) { + final int size = array.size(); + + if (size == 0) { + return NilPlaceholder.INSTANCE; + } else { + return array.deleteAt(size - 1); + } + } + + } + + @CoreMethod(names = "product", isSplatted = true) + public abstract static class ProductNode extends ArrayCoreMethodNode { + + public ProductNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ProductNode(ProductNode prev) { + super(prev); + } + + @Specialization + public Object product(RubyArray array, Object... args) { + final RubyArray[] arrays = new RubyArray[1 + args.length]; + arrays[0] = array; + System.arraycopy(args, 0, arrays, 1, args.length); + return RubyArray.product(array.getRubyClass().getContext().getCoreLibrary().getArrayClass(), arrays, arrays.length); + } + + } + + @CoreMethod(names = {"push", "<<"}, isSplatted = true) + public abstract static class PushNode extends CoreMethodNode { + + public PushNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public PushNode(PushNode prev) { + super(prev); + } + + @Specialization + public RubyArray push(RubyArray array, Object... args) { + for (int n = 0; n < args.length; n++) { + array.push(args[n]); + } + + return array; + } + + } + + @CoreMethod(names = "reject!", needsBlock = true, maxArgs = 0) + public abstract static class RejectInPlaceNode extends YieldingCoreMethodNode { + + public RejectInPlaceNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public RejectInPlaceNode(RejectInPlaceNode prev) { + super(prev); + } + + @Specialization + public Object rejectInPlace(VirtualFrame frame, RubyArray array, RubyProc block) { + boolean modified = false; + int n = 0; + + while (n < array.size()) { + if (yieldBoolean(frame, block, array.get(n))) { + array.deleteAt(n); + modified = true; + } else { + n++; + } + } + + if (modified) { + return array; + } else { + return NilPlaceholder.INSTANCE; + } + } + + } + + @CoreMethod(names = "select", needsBlock = true, maxArgs = 0) + public abstract static class SelectNode extends YieldingCoreMethodNode { + + public SelectNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SelectNode(SelectNode prev) { + super(prev); + } + + @Specialization + public Object select(VirtualFrame frame, RubyArray array, RubyProc block) { + final RubyArray result = new RubyArray(getContext().getCoreLibrary().getArrayClass()); + + for (int n = 0; n < array.size(); n++) { + final Object value = array.get(n); + + if (yieldBoolean(frame, block, value)) { + result.push(value); + } + } + + return result; + } + + } + + @CoreMethod(names = "shift", maxArgs = 0) + public abstract static class ShiftNode extends CoreMethodNode { + + public ShiftNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ShiftNode(ShiftNode prev) { + super(prev); + } + + @Specialization + public Object shift(RubyArray array) { + final int size = array.size(); + + if (size == 0) { + return NilPlaceholder.INSTANCE; + } else { + return array.deleteAt(0); + } + } + + } + + @CoreMethod(names = {"size", "length"}, maxArgs = 0) + public abstract static class SizeNode extends ArrayCoreMethodNode { + + public SizeNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SizeNode(SizeNode prev) { + super(prev); + } + + @Specialization + public int size(RubyArray array) { + return array.size(); + } + + } + + @CoreMethod(names = "sort", maxArgs = 0) + public abstract static class SortNode extends CoreMethodNode { + + public SortNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SortNode(SortNode prev) { + super(prev); + } + + @Specialization + public RubyArray sort(RubyArray array) { + final RubyContext context = array.getRubyClass().getContext(); + + final Object[] objects = array.asList().toArray(); + + Arrays.sort(objects, new Comparator() { + + @Override + public int compare(Object a, Object b) { + final RubyBasicObject aBoxed = context.getCoreLibrary().box(a); + return (int) aBoxed.getLookupNode().lookupMethod("<=>").call(null, aBoxed, null, b); + } + + }); + + return RubyArray.specializedFromObjects(context.getCoreLibrary().getArrayClass(), objects); + } + + } + + @CoreMethod(names = "unshift", isSplatted = true) + public abstract static class UnshiftNode extends CoreMethodNode { + + public UnshiftNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public UnshiftNode(UnshiftNode prev) { + super(prev); + } + + @Specialization + public Object unshift(RubyArray array, Object... args) { + for (int n = 0; n < args.length; n++) { + array.unshift(args[n]); + } + + return array; + } + + } + + @CoreMethod(names = "zip", isSplatted = true) + public abstract static class ZipNode extends CoreMethodNode { + + public ZipNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ZipNode(ZipNode prev) { + super(prev); + } + + @Specialization + public RubyArray zip(RubyArray array, Object... args) { + final RubyContext context = getContext(); + final RubyClass arrayClass = context.getCoreLibrary().getArrayClass(); + + final RubyArray result = new RubyArray(arrayClass); + + for (int n = 0; n < array.size(); n++) { + final RubyArray tuple = new RubyArray(arrayClass); + + tuple.push(array.get(n)); + + for (Object arg : args) { + final RubyArray argArray = (RubyArray) arg; + tuple.push(argArray.get(n)); + } + + result.push(tuple); + } + + return result; + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ArrayPushNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ArrayPushNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +public class ArrayPushNode extends RubyNode { + + @Child protected RubyNode array; + @Child protected RubyNode pushed; + + public ArrayPushNode(RubyContext context, SourceSection sourceSection, RubyNode array, RubyNode pushed) { + super(context, sourceSection); + this.array = adoptChild(array); + this.pushed = adoptChild(pushed); + } + + @Override + public Object execute(VirtualFrame frame) { + RubyArray a = (RubyArray) array.execute(frame); + a = (RubyArray) a.dup(); + a.push(pushed.execute(frame)); + return a; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ArrayRestNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ArrayRestNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +/** + * Take the rest of values in an array after an index, without using any method lookup. This isn't a + * call - it's an operation on a core class. + */ +@NodeInfo(shortName = "array-rest") +public final class ArrayRestNode extends RubyNode { + + final int begin; + @Child protected RubyNode array; + + public ArrayRestNode(RubyContext context, SourceSection sourceSection, int begin, RubyNode array) { + super(context, sourceSection); + this.begin = begin; + this.array = adoptChild(array); + } + + @Override + public Object execute(VirtualFrame frame) { + final RubyArray arrayObject = (RubyArray) array.execute(frame); + return arrayObject.getRangeExclusive(begin, arrayObject.size()); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/BasicObjectNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/BasicObjectNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import java.math.*; +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +@CoreClass(name = "BasicObject") +public abstract class BasicObjectNodes { + + @CoreMethod(names = "!", needsSelf = false, maxArgs = 0) + public abstract static class NotNode extends CoreMethodNode { + + public NotNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public NotNode(NotNode prev) { + super(prev); + } + + @Specialization + public boolean not() { + return false; + } + + } + + @CoreMethod(names = "==", minArgs = 1, maxArgs = 1) + public abstract static class EqualNode extends CoreMethodNode { + + public EqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EqualNode(EqualNode prev) { + super(prev); + } + + @Specialization + public boolean equal(Object a, Object b) { + // TODO(CS) ideally all classes would do this in their own nodes + return a.equals(b); + } + + } + + @CoreMethod(names = "!=", minArgs = 1, maxArgs = 1) + public abstract static class NotEqualNode extends CoreMethodNode { + + public NotEqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public NotEqualNode(NotEqualNode prev) { + super(prev); + } + + @Specialization + public boolean notEqual(Object a, Object b) { + // TODO(CS) ideally all classes would do this in their own nodes + return !a.equals(b); + } + + } + + @CoreMethod(names = "equal?", minArgs = 1, maxArgs = 1) + public abstract static class ReferenceEqualNode extends CoreMethodNode { + + public ReferenceEqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ReferenceEqualNode(ReferenceEqualNode prev) { + super(prev); + } + + @Specialization(order = 1) + public boolean equal(@SuppressWarnings("unused") NilPlaceholder a, @SuppressWarnings("unused") NilPlaceholder b) { + return true; + } + + @Specialization(order = 2) + public boolean equal(int a, int b) { + return a == b; + } + + @Specialization(order = 3) + public boolean equal(double a, double b) { + return a == b; + } + + @Specialization(order = 4) + public boolean equal(BigInteger a, BigInteger b) { + return a.compareTo(b) == 0; + } + + @Specialization(order = 5) + public boolean equal(RubyBasicObject a, RubyBasicObject b) { + return a == b; + } + } + + @CoreMethod(names = "initialize", needsSelf = false, maxArgs = 0) + public abstract static class InitializeNode extends CoreMethodNode { + + public InitializeNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InitializeNode(InitializeNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder initiailze() { + return NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = {"send", "__send__"}, needsSelf = true, needsBlock = true, minArgs = 1, isSplatted = true) + public abstract static class SendNode extends CoreMethodNode { + + public SendNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SendNode(SendNode prev) { + super(prev); + } + + @Specialization + public Object send(RubyBasicObject self, Object[] args, @SuppressWarnings("unused") UndefinedPlaceholder block) { + final String name = args[0].toString(); + final Object[] sendArgs = Arrays.copyOfRange(args, 1, args.length); + return self.send(name, null, sendArgs); + } + + @Specialization + public Object send(RubyBasicObject self, Object[] args, RubyProc block) { + final String name = args[0].toString(); + final Object[] sendArgs = Arrays.copyOfRange(args, 1, args.length); + return self.send(name, block, sendArgs); + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/BignumNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/BignumNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,642 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import java.math.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +@CoreClass(name = "Bignum") +public abstract class BignumNodes { + + @CoreMethod(names = "+@", maxArgs = 0) + public abstract static class PosNode extends CoreMethodNode { + + public PosNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public PosNode(PosNode prev) { + super(prev); + } + + @Specialization + public BigInteger pos(BigInteger value) { + return value; + } + + } + + @CoreMethod(names = "-@", maxArgs = 0) + public abstract static class NegNode extends CoreMethodNode { + + public NegNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public NegNode(NegNode prev) { + super(prev); + } + + @Specialization + public BigInteger neg(BigInteger value) { + return value.negate(); + } + + } + + @CoreMethod(names = "+", minArgs = 1, maxArgs = 1) + public abstract static class AddNode extends CoreMethodNode { + + public AddNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public AddNode(AddNode prev) { + super(prev); + } + + @Specialization + public Object add(BigInteger a, int b) { + return a.add(BigInteger.valueOf(b)); + } + + @Specialization + public double add(BigInteger a, double b) { + return a.doubleValue() + b; + } + + @Specialization + public Object add(BigInteger a, BigInteger b) { + return GeneralConversions.fixnumOrBignum(a.add(b)); + } + + } + + @CoreMethod(names = "-", minArgs = 1, maxArgs = 1) + public abstract static class SubNode extends CoreMethodNode { + + public SubNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SubNode(SubNode prev) { + super(prev); + } + + @Specialization + public Object sub(BigInteger a, int b) { + return a.subtract(BigInteger.valueOf(b)); + } + + @Specialization + public double sub(BigInteger a, double b) { + return a.doubleValue() - b; + } + + @Specialization + public Object sub(BigInteger a, BigInteger b) { + return GeneralConversions.fixnumOrBignum(a.subtract(b)); + } + + } + + @CoreMethod(names = "*", minArgs = 1, maxArgs = 1) + public abstract static class MulNode extends CoreMethodNode { + + public MulNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public MulNode(MulNode prev) { + super(prev); + } + + @Specialization + public Object mul(BigInteger a, int b) { + return a.multiply(BigInteger.valueOf(b)); + } + + @Specialization + public double mul(BigInteger a, double b) { + return a.doubleValue() * b; + } + + @Specialization + public Object mul(BigInteger a, BigInteger b) { + return GeneralConversions.fixnumOrBignum(a.multiply(b)); + } + + } + + @CoreMethod(names = "**", minArgs = 1, maxArgs = 1) + public abstract static class PowNode extends CoreMethodNode { + + public PowNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public PowNode(PowNode prev) { + super(prev); + } + + @Specialization + public BigInteger pow(BigInteger a, int b) { + return a.pow(b); + } + + @Specialization + public double pow(BigInteger a, double b) { + return Math.pow(a.doubleValue(), b); + } + + @Specialization + public BigInteger pow(BigInteger a, BigInteger b) { + BigInteger result = BigInteger.ONE; + + for (BigInteger n = BigInteger.ZERO; b.compareTo(b) < 0; n = n.add(BigInteger.ONE)) { + result = result.multiply(a); + } + + return result; + } + + } + + @CoreMethod(names = "/", minArgs = 1, maxArgs = 1) + public abstract static class DivNode extends CoreMethodNode { + + public DivNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public DivNode(DivNode prev) { + super(prev); + } + + @Specialization + public Object div(BigInteger a, int b) { + return a.divide(BigInteger.valueOf(b)); + } + + @Specialization + public double div(BigInteger a, double b) { + return a.doubleValue() / b; + } + + @Specialization + public Object div(BigInteger a, BigInteger b) { + return GeneralConversions.fixnumOrBignum(a.divide(b)); + } + + } + + @CoreMethod(names = "%", minArgs = 1, maxArgs = 1) + public abstract static class ModNode extends CoreMethodNode { + + public ModNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ModNode(ModNode prev) { + super(prev); + } + + @Specialization + public Object mod(BigInteger a, int b) { + return GeneralConversions.fixnumOrBignum(a.mod(BigInteger.valueOf(b))); + } + + @Specialization + public Object mod(@SuppressWarnings("unused") BigInteger a, @SuppressWarnings("unused") double b) { + throw new UnsupportedOperationException(); + } + + @Specialization + public Object mod(BigInteger a, BigInteger b) { + return GeneralConversions.fixnumOrBignum(a.mod(b)); + } + + } + + @CoreMethod(names = "divmod", minArgs = 1, maxArgs = 1) + public abstract static class DivModNode extends CoreMethodNode { + + public DivModNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public DivModNode(DivModNode prev) { + super(prev); + } + + @SuppressWarnings("unused") + @Specialization + public RubyArray divMod(VirtualFrame frame, BigInteger a, int b) { + return RubyBignum.divMod(getContext(), a, BigInteger.valueOf(b)); + } + + @Specialization + public RubyArray divMod(@SuppressWarnings("unused") BigInteger a, @SuppressWarnings("unused") double b) { + throw new UnsupportedOperationException(); + } + + @Specialization + public RubyArray divMod(BigInteger a, BigInteger b) { + return RubyBignum.divMod(getContext(), a, b); + } + + } + + @CoreMethod(names = "<", minArgs = 1, maxArgs = 1) + public abstract static class LessNode extends CoreMethodNode { + + public LessNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public LessNode(LessNode prev) { + super(prev); + } + + @Specialization + public boolean less(BigInteger a, int b) { + return a.compareTo(BigInteger.valueOf(b)) < 0; + } + + @Specialization + public boolean less(BigInteger a, double b) { + return a.compareTo(BigInteger.valueOf((long) b)) < 0; + } + + @Specialization + public boolean less(BigInteger a, BigInteger b) { + return a.compareTo(b) < 0; + } + } + + @CoreMethod(names = "<=", minArgs = 1, maxArgs = 1) + public abstract static class LessEqualNode extends CoreMethodNode { + + public LessEqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public LessEqualNode(LessEqualNode prev) { + super(prev); + } + + @Specialization + public boolean lessEqual(BigInteger a, int b) { + return a.compareTo(BigInteger.valueOf(b)) <= 0; + } + + @Specialization + public boolean lessEqual(BigInteger a, double b) { + return a.compareTo(BigInteger.valueOf((long) b)) <= 0; + } + + @Specialization + public boolean lessEqual(BigInteger a, BigInteger b) { + return a.compareTo(b) <= 0; + } + } + + @CoreMethod(names = "==", minArgs = 1, maxArgs = 1) + public abstract static class EqualNode extends CoreMethodNode { + + public EqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EqualNode(EqualNode prev) { + super(prev); + } + + @Specialization + public boolean equal(BigInteger a, int b) { + return a.compareTo(BigInteger.valueOf(b)) == 0; + } + + @Specialization + public boolean equal(BigInteger a, double b) { + return a.compareTo(BigInteger.valueOf((long) b)) == 0; + } + + @Specialization + public boolean equal(BigInteger a, BigInteger b) { + return a.compareTo(b) == 0; + } + } + + @CoreMethod(names = "<=>", minArgs = 1, maxArgs = 1) + public abstract static class CompareNode extends CoreMethodNode { + + public CompareNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public CompareNode(CompareNode prev) { + super(prev); + } + + @Specialization + public int compare(BigInteger a, int b) { + return a.compareTo(BigInteger.valueOf(b)); + } + + @Specialization + public int compare(BigInteger a, double b) { + return a.compareTo(BigInteger.valueOf((long) b)); + } + + @Specialization + public int compare(BigInteger a, BigInteger b) { + return a.compareTo(b); + } + } + + @CoreMethod(names = "!=", minArgs = 1, maxArgs = 1) + public abstract static class NotEqualNode extends CoreMethodNode { + + public NotEqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public NotEqualNode(NotEqualNode prev) { + super(prev); + } + + @Specialization + public boolean notEqual(BigInteger a, int b) { + return a.compareTo(BigInteger.valueOf(b)) != 0; + } + + @Specialization + public boolean notEqual(BigInteger a, double b) { + return a.compareTo(BigInteger.valueOf((long) b)) != 0; + } + + @Specialization + public boolean notEqual(BigInteger a, BigInteger b) { + return a.compareTo(b) != 0; + } + } + + @CoreMethod(names = ">=", minArgs = 1, maxArgs = 1) + public abstract static class GreaterEqualNode extends CoreMethodNode { + + public GreaterEqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public GreaterEqualNode(GreaterEqualNode prev) { + super(prev); + } + + @Specialization + public boolean greaterEqual(BigInteger a, int b) { + return a.compareTo(BigInteger.valueOf(b)) >= 0; + } + + @Specialization + public boolean greaterEqual(BigInteger a, double b) { + return a.compareTo(BigInteger.valueOf((long) b)) >= 0; + } + + @Specialization + public boolean greaterEqual(BigInteger a, BigInteger b) { + return a.compareTo(b) >= 0; + } + } + + @CoreMethod(names = ">", minArgs = 1, maxArgs = 1) + public abstract static class GreaterNode extends CoreMethodNode { + + public GreaterNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public GreaterNode(GreaterNode prev) { + super(prev); + } + + @Specialization + public boolean equal(BigInteger a, int b) { + return a.compareTo(BigInteger.valueOf(b)) > 0; + } + + @Specialization + public boolean equal(BigInteger a, double b) { + return a.compareTo(BigInteger.valueOf((long) b)) > 0; + } + + @Specialization + public boolean equal(BigInteger a, BigInteger b) { + return a.compareTo(b) > 0; + } + } + + @CoreMethod(names = "&", minArgs = 1, maxArgs = 1) + public abstract static class BitAndNode extends CoreMethodNode { + + public BitAndNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public BitAndNode(BitAndNode prev) { + super(prev); + } + + @Specialization + public Object bitAnd(BigInteger a, int b) { + return GeneralConversions.fixnumOrBignum(a.and(BigInteger.valueOf(b))); + } + + @Specialization + public Object bitAnd(BigInteger a, BigInteger b) { + return GeneralConversions.fixnumOrBignum(a.and(b)); + } + } + + @CoreMethod(names = "|", minArgs = 1, maxArgs = 1) + public abstract static class BitOrNode extends CoreMethodNode { + + public BitOrNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public BitOrNode(BitOrNode prev) { + super(prev); + } + + @Specialization + public Object bitOr(BigInteger a, int b) { + return GeneralConversions.fixnumOrBignum(a.or(BigInteger.valueOf(b))); + } + + @Specialization + public Object bitOr(BigInteger a, BigInteger b) { + return GeneralConversions.fixnumOrBignum(a.or(b)); + } + } + + @CoreMethod(names = "^", minArgs = 1, maxArgs = 1) + public abstract static class BitXOrNode extends CoreMethodNode { + + public BitXOrNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public BitXOrNode(BitXOrNode prev) { + super(prev); + } + + @Specialization + public Object bitXOr(BigInteger a, int b) { + return GeneralConversions.fixnumOrBignum(a.xor(BigInteger.valueOf(b))); + } + + @Specialization + public Object bitXOr(BigInteger a, BigInteger b) { + return GeneralConversions.fixnumOrBignum(a.xor(b)); + } + } + + @CoreMethod(names = "<<", minArgs = 1, maxArgs = 1) + public abstract static class LeftShiftNode extends CoreMethodNode { + + public LeftShiftNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public LeftShiftNode(LeftShiftNode prev) { + super(prev); + } + + @Specialization + public Object leftShift(BigInteger a, int b) { + if (b >= 0) { + return GeneralConversions.fixnumOrBignum(a.shiftLeft(b)); + } else { + return GeneralConversions.fixnumOrBignum(a.shiftRight(-b)); + } + } + + } + + @CoreMethod(names = ">>", minArgs = 1, maxArgs = 1) + public abstract static class RightShiftNode extends CoreMethodNode { + + public RightShiftNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public RightShiftNode(RightShiftNode prev) { + super(prev); + } + + @Specialization + public Object leftShift(BigInteger a, int b) { + if (b >= 0) { + return GeneralConversions.fixnumOrBignum(a.shiftRight(b)); + } else { + return GeneralConversions.fixnumOrBignum(a.shiftLeft(-b)); + } + } + + } + + @CoreMethod(names = "inspect", maxArgs = 0) + public abstract static class InpsectNode extends CoreMethodNode { + + public InpsectNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InpsectNode(InpsectNode prev) { + super(prev); + } + + @Specialization + public RubyString inspect(BigInteger n) { + return getContext().makeString(n.toString()); + } + + } + + @CoreMethod(names = "nonzero?", maxArgs = 0) + public abstract static class NonZeroNode extends CoreMethodNode { + + public NonZeroNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public NonZeroNode(NonZeroNode prev) { + super(prev); + } + + @Specialization + public Object nonZero(BigInteger value) { + if (value.compareTo(BigInteger.ZERO) == 0) { + return false; + } else { + return value; + } + } + + } + + @CoreMethod(names = "times", needsBlock = true, maxArgs = 0) + public abstract static class TimesNode extends YieldingCoreMethodNode { + + public TimesNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public TimesNode(TimesNode prev) { + super(prev); + } + + @Specialization + public BigInteger times(VirtualFrame frame, BigInteger n, RubyProc block) { + for (BigInteger i = BigInteger.ZERO; i.compareTo(n) < 0; i = i.add(BigInteger.ONE)) { + yield(frame, block, i); + } + + return n; + } + + } + + @CoreMethod(names = "to_s", maxArgs = 0) + public abstract static class ToSNode extends CoreMethodNode { + + public ToSNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToSNode(ToSNode prev) { + super(prev); + } + + @Specialization + public RubyString toS(BigInteger value) { + return getContext().makeString(value.toString()); + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ClassNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ClassNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.call.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +@CoreClass(name = "Class") +public abstract class ClassNodes { + + @CoreMethod(names = "===", minArgs = 1, maxArgs = 1) + public abstract static class ContainsInstanceNode extends CoreMethodNode { + + public ContainsInstanceNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ContainsInstanceNode(ContainsInstanceNode prev) { + super(prev); + } + + @Specialization + public boolean containsInstance(RubyClass rubyClass, RubyBasicObject instance) { + return instance.getRubyClass().assignableTo(rubyClass); + } + } + + @CoreMethod(names = "new", needsBlock = true, isSplatted = true) + public abstract static class NewNode extends CoreMethodNode { + + @Child protected DispatchHeadNode initialize; + + public NewNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + initialize = adoptChild(new DispatchHeadNode(context, getSourceSection(), "initialize", false)); + } + + public NewNode(NewNode prev) { + super(prev); + initialize = adoptChild(prev.initialize); + } + + @Specialization + public RubyBasicObject newInstance(VirtualFrame frame, RubyClass rubyClass, Object[] args, @SuppressWarnings("unused") UndefinedPlaceholder block) { + return doNewInstance(frame, rubyClass, args, null); + } + + @Specialization + public RubyBasicObject newInstance(VirtualFrame frame, RubyClass rubyClass, Object[] args, RubyProc block) { + return doNewInstance(frame, rubyClass, args, block); + } + + private RubyBasicObject doNewInstance(VirtualFrame frame, RubyClass rubyClass, Object[] args, RubyProc block) { + final RubyBasicObject instance = rubyClass.newInstance(); + initialize.dispatch(frame, instance, block, args); + return instance; + } + + } + + @CoreMethod(names = "to_s", maxArgs = 0) + public abstract static class ToSNode extends CoreMethodNode { + + public ToSNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToSNode(ToSNode prev) { + super(prev); + } + + @Specialization + public RubyString toS(RubyClass rubyClass) { + return getContext().makeString(rubyClass.getName()); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ComparableNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ComparableNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.call.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +@CoreClass(name = "Comparable") +public abstract class ComparableNodes { + + public abstract static class ComparableCoreMethodNode extends CoreMethodNode { + + @Child protected DispatchHeadNode compareNode; + + public ComparableCoreMethodNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + compareNode = adoptChild(new DispatchHeadNode(context, getSourceSection(), "<=>", false)); + } + + public ComparableCoreMethodNode(ComparableCoreMethodNode prev) { + super(prev); + compareNode = adoptChild(prev.compareNode); + } + + public int compare(VirtualFrame frame, RubyBasicObject receiverObject, Object comparedTo) { + return (int) compareNode.dispatch(frame, receiverObject, null, comparedTo); + } + + } + + @CoreMethod(names = "<", isModuleMethod = true, minArgs = 1, maxArgs = 1) + public abstract static class LessNode extends ComparableCoreMethodNode { + + public LessNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public LessNode(LessNode prev) { + super(prev); + } + + @Specialization + public boolean less(VirtualFrame frame, RubyBasicObject self, Object comparedTo) { + return compare(frame, self, comparedTo) < 0; + } + + } + + @CoreMethod(names = "<=", isModuleMethod = true, minArgs = 1, maxArgs = 1) + public abstract static class LessEqualNode extends ComparableCoreMethodNode { + + public LessEqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public LessEqualNode(LessEqualNode prev) { + super(prev); + } + + @Specialization + public boolean lessEqual(VirtualFrame frame, RubyBasicObject self, Object comparedTo) { + return compare(frame, self, comparedTo) <= 0; + } + + } + + @CoreMethod(names = "==", isModuleMethod = true, minArgs = 1, maxArgs = 1) + public abstract static class EqualNode extends ComparableCoreMethodNode { + + public EqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EqualNode(EqualNode prev) { + super(prev); + } + + @Specialization + public boolean equal(VirtualFrame frame, RubyBasicObject self, Object comparedTo) { + if (self == comparedTo) { + return true; + } + + try { + return compare(frame, self, comparedTo) == 0; + } catch (Exception e) { + // Comparable#== catches and ignores all exceptions in <=>, returning false + return false; + } + } + } + + @CoreMethod(names = ">=", isModuleMethod = true, minArgs = 1, maxArgs = 1) + public abstract static class GreaterEqualNode extends ComparableCoreMethodNode { + + public GreaterEqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public GreaterEqualNode(GreaterEqualNode prev) { + super(prev); + } + + @Specialization + public boolean greaterEqual(VirtualFrame frame, RubyBasicObject self, Object comparedTo) { + return compare(frame, self, comparedTo) >= 0; + } + + } + + @CoreMethod(names = ">", isModuleMethod = true, minArgs = 1, maxArgs = 1) + public abstract static class GreaterNode extends ComparableCoreMethodNode { + + public GreaterNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public GreaterNode(GreaterNode prev) { + super(prev); + } + + @Specialization + public boolean greater(VirtualFrame frame, RubyBasicObject self, Object comparedTo) { + return compare(frame, self, comparedTo) > 0; + } + + } + + @CoreMethod(names = "between?", isModuleMethod = true, minArgs = 2, maxArgs = 2) + public abstract static class BetweenNode extends ComparableCoreMethodNode { + + public BetweenNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public BetweenNode(BetweenNode prev) { + super(prev); + } + + @Specialization + public boolean between(VirtualFrame frame, RubyBasicObject self, Object min, Object max) { + return !(compare(frame, self, min) < 0 || compare(frame, self, max) > 0); + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ContinuationNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ContinuationNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +@CoreClass(name = "Continuation") +public abstract class ContinuationNodes { + + @CoreMethod(names = "call", isSplatted = true) + public abstract static class CallNode extends CoreMethodNode { + + public CallNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public CallNode(CallNode prev) { + super(prev); + } + + @Specialization + public Object call(RubyContinuation continuation, Object[] args) { + continuation.call(args); + return null; + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/CoreClass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/CoreClass.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import java.lang.annotation.*; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface CoreClass { + + String name(); + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/CoreMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/CoreMethod.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import java.lang.annotation.*; + +import com.oracle.truffle.ruby.runtime.configuration.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface CoreMethod { + + String[] names(); + + boolean isModuleMethod() default false; + + boolean needsSelf() default true; + + boolean isSplatted() default false; + + boolean needsBlock() default false; + + boolean appendCallNode() default false; + + RubyVersion[] versions() default {RubyVersion.RUBY_18, RubyVersion.RUBY_19, RubyVersion.RUBY_20, RubyVersion.RUBY_21}; + + int minArgs() default Arity.NO_MINIMUM; + + int maxArgs() default Arity.NO_MAXIMUM; + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/CoreMethodNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/CoreMethodNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +@NodeChild(value = "arguments", type = RubyNode[].class) +public abstract class CoreMethodNode extends RubyNode { + + public CoreMethodNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public CoreMethodNode(CoreMethodNode prev) { + super(prev); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/CoreMethodNodeManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/CoreMethodNodeManager.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.nodes.control.*; +import com.oracle.truffle.ruby.nodes.debug.*; +import com.oracle.truffle.ruby.nodes.methods.arguments.*; +import com.oracle.truffle.ruby.nodes.objects.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +public abstract class CoreMethodNodeManager { + + /** + * Register all the nodes that represent core methods as methods with their respective classes, + * given the Object class object, which should already be initialized with all the core classes. + */ + public static void addMethods(RubyClass rubyObjectClass) { + for (MethodDetails methodDetails : getMethods()) { + if (Arrays.asList(methodDetails.getMethodAnnotation().versions()).contains(rubyObjectClass.getContext().getConfiguration().getRubyVersion())) { + addMethod(rubyObjectClass, methodDetails); + } + } + } + + /** + * Collect up all the core method nodes. Abstracted to allow the SVM to implement at compile + * type. + */ + public static List getMethods() { + final List methods = new ArrayList<>(); + getMethods(methods, ArrayNodesFactory.getFactories()); + getMethods(methods, BasicObjectNodesFactory.getFactories()); + getMethods(methods, BignumNodesFactory.getFactories()); + getMethods(methods, ClassNodesFactory.getFactories()); + getMethods(methods, ContinuationNodesFactory.getFactories()); + getMethods(methods, ComparableNodesFactory.getFactories()); + getMethods(methods, DebugNodesFactory.getFactories()); + getMethods(methods, DirNodesFactory.getFactories()); + getMethods(methods, ExceptionNodesFactory.getFactories()); + getMethods(methods, FalseClassNodesFactory.getFactories()); + getMethods(methods, FiberNodesFactory.getFactories()); + getMethods(methods, FileNodesFactory.getFactories()); + getMethods(methods, FixnumNodesFactory.getFactories()); + getMethods(methods, FloatNodesFactory.getFactories()); + getMethods(methods, HashNodesFactory.getFactories()); + getMethods(methods, KernelNodesFactory.getFactories()); + getMethods(methods, MainNodesFactory.getFactories()); + getMethods(methods, MatchDataNodesFactory.getFactories()); + getMethods(methods, MathNodesFactory.getFactories()); + getMethods(methods, ModuleNodesFactory.getFactories()); + getMethods(methods, NilClassNodesFactory.getFactories()); + getMethods(methods, ObjectNodesFactory.getFactories()); + getMethods(methods, ObjectSpaceNodesFactory.getFactories()); + getMethods(methods, ProcessNodesFactory.getFactories()); + getMethods(methods, ProcNodesFactory.getFactories()); + getMethods(methods, RangeNodesFactory.getFactories()); + getMethods(methods, RegexpNodesFactory.getFactories()); + getMethods(methods, SignalNodesFactory.getFactories()); + getMethods(methods, StringNodesFactory.getFactories()); + getMethods(methods, StructNodesFactory.getFactories()); + getMethods(methods, SymbolNodesFactory.getFactories()); + getMethods(methods, ThreadNodesFactory.getFactories()); + getMethods(methods, TimeNodesFactory.getFactories()); + getMethods(methods, TrueClassNodesFactory.getFactories()); + return methods; + } + + /** + * Collect up the core methods created by a factory. + */ + private static void getMethods(List methods, List> nodeFactories) { + for (NodeFactory nodeFactory : nodeFactories) { + final GeneratedBy generatedBy = nodeFactory.getClass().getAnnotation(GeneratedBy.class); + final Class nodeClass = generatedBy.value(); + final CoreClass classAnnotation = nodeClass.getEnclosingClass().getAnnotation(CoreClass.class); + final CoreMethod methodAnnotation = nodeClass.getAnnotation(CoreMethod.class); + methods.add(new MethodDetails(classAnnotation, methodAnnotation, nodeFactory)); + } + } + + /** + * Take a core method node factory, the annotations for the class and method, and add it as a + * method on the correct class. + */ + private static void addMethod(RubyClass rubyObjectClass, MethodDetails methodDetails) { + assert rubyObjectClass != null; + assert methodDetails != null; + + final RubyContext context = rubyObjectClass.getContext(); + + RubyModule module; + + if (methodDetails.getClassAnnotation().name().equals("main")) { + module = context.getCoreLibrary().getMainObject().getSingletonClass(); + } else { + module = (RubyModule) rubyObjectClass.lookupConstant(methodDetails.getClassAnnotation().name()); + } + + assert module != null : methodDetails.getClassAnnotation().name(); + + final List names = Arrays.asList(methodDetails.getMethodAnnotation().names()); + assert names.size() >= 1; + + final String canonicalName = names.get(0); + final List aliases = names.subList(1, names.size()); + + final UniqueMethodIdentifier uniqueIdentifier = new UniqueMethodIdentifier(); + final Visibility visibility = Visibility.PUBLIC; + + final RubyRootNode pristineRootNode = makeGenericMethod(context, methodDetails); + final CallTarget callTarget = Truffle.getRuntime().createCallTarget(NodeUtil.cloneNode(pristineRootNode)); + + final String intrinsicName = methodDetails.getClassAnnotation().name() + "#" + canonicalName; + + final InlinableMethodImplementation methodImplementation = new InlinableMethodImplementation(callTarget, null, new FrameDescriptor(), pristineRootNode, true, + methodDetails.getMethodAnnotation().appendCallNode()); + final RubyMethod method = new RubyMethod(pristineRootNode.getSourceSection(), module, uniqueIdentifier, intrinsicName, canonicalName, visibility, false, methodImplementation); + + module.addMethod(method); + + if (methodDetails.getMethodAnnotation().isModuleMethod()) { + module.getSingletonClass().addMethod(method); + } + + for (String alias : aliases) { + final RubyMethod withAlias = method.withNewName(alias); + + module.addMethod(withAlias); + + if (methodDetails.getMethodAnnotation().isModuleMethod()) { + module.getSingletonClass().addMethod(withAlias); + } + } + } + + private static RubyRootNode makeGenericMethod(RubyContext context, MethodDetails methodDetails) { + final SourceSection sourceSection = new CoreSourceSection(methodDetails.getClassAnnotation().name() + "#" + methodDetails.getMethodAnnotation().names()[0]); + + final Arity arity = new Arity(methodDetails.getMethodAnnotation().minArgs(), methodDetails.getMethodAnnotation().maxArgs()); + + final List argumentsNodes = new ArrayList<>(); + + if (methodDetails.getMethodAnnotation().needsSelf()) { + argumentsNodes.add(new SelfNode(context, sourceSection)); + } + + if (methodDetails.getMethodAnnotation().isSplatted()) { + argumentsNodes.add(new ReadAllArgumentsNode(context, sourceSection)); + } else { + assert arity.getMaximum() != Arity.NO_MAXIMUM; + + for (int n = 0; n < arity.getMaximum(); n++) { + argumentsNodes.add(new ReadPreArgumentNode(context, sourceSection, n, true)); + } + } + + if (methodDetails.getMethodAnnotation().needsBlock()) { + argumentsNodes.add(new ReadBlockArgumentNode(context, sourceSection, true)); + } + + final RubyNode methodNode = methodDetails.getNodeFactory().createNode(context, sourceSection, argumentsNodes.toArray(new RubyNode[argumentsNodes.size()])); + final CheckArityNode checkArity = new CheckArityNode(context, sourceSection, arity); + final SequenceNode block = new SequenceNode(context, sourceSection, checkArity, methodNode); + + return new RubyRootNode(sourceSection, methodDetails.getClassAnnotation().name() + "#" + methodDetails.getMethodAnnotation().names()[0] + "(core)", block); + } + + public static class MethodDetails { + + private final CoreClass classAnnotation; + private final CoreMethod methodAnnotation; + private final NodeFactory nodeFactory; + + public MethodDetails(CoreClass classAnnotation, CoreMethod methodAnnotation, NodeFactory nodeFactory) { + assert classAnnotation != null; + assert methodAnnotation != null; + assert nodeFactory != null; + this.classAnnotation = classAnnotation; + this.methodAnnotation = methodAnnotation; + this.nodeFactory = nodeFactory; + } + + public CoreClass getClassAnnotation() { + return classAnnotation; + } + + public CoreMethod getMethodAnnotation() { + return methodAnnotation; + } + + public NodeFactory getNodeFactory() { + return nodeFactory; + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/DirNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/DirNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import java.io.*; +import java.nio.file.*; +import java.nio.file.attribute.*; + +import com.oracle.truffle.api.CompilerDirectives.SlowPath; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +@CoreClass(name = "Dir") +public abstract class DirNodes { + + @CoreMethod(names = "[]", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class GlobNode extends CoreMethodNode { + + public GlobNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public GlobNode(GlobNode prev) { + super(prev); + } + + @Specialization + public RubyArray glob(RubyString glob) { + return glob(getContext(), glob.toString()); + } + + @SlowPath + private static RubyArray glob(final RubyContext context, String glob) { + /* + * Globbing is quite complicated. We've implemented a subset of the functionality that + * satisfies MSpec, but it will likely break for anyone else. + */ + + context.implementationMessage("globbing %s", glob); + + String absoluteGlob; + + if (!glob.startsWith("/")) { + absoluteGlob = new File(".", glob).getAbsolutePath().toString(); + } else { + absoluteGlob = glob; + } + + // Get the first star + + final int firstStar = absoluteGlob.indexOf('*'); + assert firstStar >= 0; + + // Walk back from that to the first / before that star + + int prefixLength = firstStar; + + while (prefixLength > 0 && absoluteGlob.charAt(prefixLength) == File.separatorChar) { + prefixLength--; + } + + final String prefix = absoluteGlob.substring(0, prefixLength - 1); + + final PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + absoluteGlob.substring(prefixLength)); + + final RubyArray array = new RubyArray(context.getCoreLibrary().getArrayClass()); + + try { + Files.walkFileTree(FileSystems.getDefault().getPath(prefix), new SimpleFileVisitor() { + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + if (matcher.matches(file)) { + array.push(context.makeString(file.toString())); + } + + return FileVisitResult.CONTINUE; + } + + }); + } catch (IOException e) { + throw new RuntimeException(e); + } + + return array; + } + + } + + @CoreMethod(names = "chdir", isModuleMethod = true, needsSelf = false, needsBlock = true, minArgs = 1, maxArgs = 1) + public abstract static class ChdirNode extends YieldingCoreMethodNode { + + public ChdirNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ChdirNode(ChdirNode prev) { + super(prev); + } + + @Specialization + public Object chdir(VirtualFrame frame, RubyString path, RubyProc block) { + final RubyContext context = getContext(); + + final String previous = context.getCurrentDirectory(); + context.setCurrentDirectory(path.toString()); + + if (block != null) { + try { + return yield(frame, block, path); + } finally { + context.setCurrentDirectory(previous); + } + } else { + return 0; + } + } + + } + + @CoreMethod(names = {"exist?", "exists?"}, isModuleMethod = true, needsSelf = false, maxArgs = 1) + public abstract static class ExistsNode extends CoreMethodNode { + + public ExistsNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ExistsNode(ExistsNode prev) { + super(prev); + } + + @Specialization + public boolean exists(RubyString path) { + return new File(path.toString()).isDirectory(); + } + + } + + @CoreMethod(names = "pwd", isModuleMethod = true, needsSelf = false, maxArgs = 0) + public abstract static class PwdNode extends CoreMethodNode { + + public PwdNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public PwdNode(PwdNode prev) { + super(prev); + } + + @Specialization + public RubyString pwd() { + return getContext().makeString(getContext().getCurrentDirectory()); + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ExceptionNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ExceptionNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +@CoreClass(name = "Exception") +public abstract class ExceptionNodes { + + @CoreMethod(names = "initialize", minArgs = 0, maxArgs = 1) + public abstract static class InitializeNode extends CoreMethodNode { + + public InitializeNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InitializeNode(InitializeNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder initialize(RubyException exception, @SuppressWarnings("unused") UndefinedPlaceholder message) { + exception.initialize(getContext().makeString(" ")); + return NilPlaceholder.INSTANCE; + } + + @Specialization + public NilPlaceholder initialize(RubyException exception, RubyString message) { + exception.initialize(message); + return NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = "backtrace", needsSelf = false, maxArgs = 0) + public abstract static class BacktraceNode extends CoreMethodNode { + + public BacktraceNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public BacktraceNode(BacktraceNode prev) { + super(prev); + } + + @Specialization + public RubyArray backtrace() { + return new RubyArray(getContext().getCoreLibrary().getArrayClass()); + } + + } + + @CoreMethod(names = "message", maxArgs = 0) + public abstract static class MessageNode extends CoreMethodNode { + + public MessageNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public MessageNode(MessageNode prev) { + super(prev); + } + + @Specialization + public RubyString message(RubyException exception) { + return exception.getMessage(); + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/FalseClassNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/FalseClassNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +@CoreClass(name = "FalseClass") +public abstract class FalseClassNodes { + + @CoreMethod(names = "!", needsSelf = false, maxArgs = 0) + public abstract static class NotNode extends CoreMethodNode { + + public NotNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public NotNode(NotNode prev) { + super(prev); + } + + @Specialization + public boolean not() { + return true; + } + + } + + @CoreMethod(names = {"==", "===", "=~"}, needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class EqualNode extends CoreMethodNode { + + public EqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EqualNode(EqualNode prev) { + super(prev); + } + + @Specialization + public boolean equal(boolean other) { + return !other; + } + + @Specialization + public boolean equal(Object other) { + return other instanceof Boolean && !((boolean) other); + } + + } + + @CoreMethod(names = "^", needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class XorNode extends CoreMethodNode { + + public XorNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public XorNode(XorNode prev) { + super(prev); + } + + @Specialization + public boolean xor(boolean other) { + return false ^ other; + } + + } + + @CoreMethod(names = "to_s", needsSelf = false, maxArgs = 0) + public abstract static class ToSNode extends CoreMethodNode { + + public ToSNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToSNode(ToSNode prev) { + super(prev); + } + + @Specialization + public RubyString toS() { + return getContext().makeString("false"); + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/FiberNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/FiberNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +@CoreClass(name = "Fiber") +public abstract class FiberNodes { + + @CoreMethod(names = "resume", isSplatted = true) + public abstract static class ResumeNode extends CoreMethodNode { + + public ResumeNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ResumeNode(ResumeNode prev) { + super(prev); + } + + @Specialization + public Object resume(RubyFiber fiberBeingResumed, Object[] args) { + final RubyFiber sendingFiber = getContext().getFiberManager().getCurrentFiber(); + + fiberBeingResumed.resume(sendingFiber, args); + + return sendingFiber.waitForResume(); + } + + } + + @CoreMethod(names = "initialize", needsBlock = true, maxArgs = 0) + public abstract static class InitializeNode extends CoreMethodNode { + + public InitializeNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InitializeNode(InitializeNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder initialize(RubyFiber fiber, RubyProc block) { + fiber.initialize(block); + return NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = "yield", isModuleMethod = true, needsSelf = false, isSplatted = true) + public abstract static class YieldNode extends CoreMethodNode { + + public YieldNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public YieldNode(YieldNode prev) { + super(prev); + } + + @Specialization + public Object yield(Object[] args) { + final RubyFiber yieldingFiber = getContext().getFiberManager().getCurrentFiber(); + final RubyFiber fiberYieldedTo = yieldingFiber.lastResumedByFiber; + + fiberYieldedTo.resume(yieldingFiber, args); + + return yieldingFiber.waitForResume(); + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/FileNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/FileNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import java.io.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +@CoreClass(name = "File") +public abstract class FileNodes { + + @CoreMethod(names = "absolute_path", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class AbsolutePathNode extends CoreMethodNode { + + public AbsolutePathNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public AbsolutePathNode(AbsolutePathNode prev) { + super(prev); + } + + @Specialization + public RubyString absolutePath(RubyString path) { + return getContext().makeString(new File(path.toString()).getAbsolutePath()); + } + + } + + @CoreMethod(names = "close", maxArgs = 0) + public abstract static class CloseNode extends CoreMethodNode { + + public CloseNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public CloseNode(CloseNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder close(RubyFile file) { + file.close(); + return NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = "directory?", isModuleMethod = true, needsSelf = false, maxArgs = 1) + public abstract static class DirectoryNode extends CoreMethodNode { + + public DirectoryNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public DirectoryNode(DirectoryNode prev) { + super(prev); + } + + @Specialization + public boolean directory(RubyString path) { + return new File(path.toString()).isDirectory(); + } + + } + + @CoreMethod(names = "dirname", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class DirnameNode extends CoreMethodNode { + + public DirnameNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public DirnameNode(DirnameNode prev) { + super(prev); + } + + @Specialization + public RubyString dirname(RubyString path) { + final String parent = new File(path.toString()).getParent(); + + if (parent == null) { + return getContext().makeString("."); + } else { + return getContext().makeString(parent); + } + } + + } + + @CoreMethod(names = "each_line", needsBlock = true, maxArgs = 0) + public abstract static class EachLineNode extends YieldingCoreMethodNode { + + public EachLineNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EachLineNode(EachLineNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder eachLine(VirtualFrame frame, RubyFile file, RubyProc block) { + final RubyContext context = getContext(); + + // TODO(cs): this buffered reader may consume too much + + final BufferedReader lineReader = new BufferedReader(file.getReader()); + + while (true) { + String line; + + try { + line = lineReader.readLine(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + if (line == null) { + break; + } + + yield(frame, block, context.makeString(line)); + } + + return NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = {"exist?", "exists?"}, isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class ExistsNode extends CoreMethodNode { + + public ExistsNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ExistsNode(ExistsNode prev) { + super(prev); + } + + @Specialization + public boolean exists(RubyString path) { + return new File(path.toString()).isFile(); + } + + } + + @CoreMethod(names = "executable?", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class ExecutableNode extends CoreMethodNode { + + public ExecutableNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ExecutableNode(ExecutableNode prev) { + super(prev); + } + + @Specialization + public boolean executable(RubyString path) { + return new File(path.toString()).canExecute(); + } + + } + + @CoreMethod(names = "expand_path", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 2) + public abstract static class ExpandPathNode extends CoreMethodNode { + + public ExpandPathNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ExpandPathNode(ExpandPathNode prev) { + super(prev); + } + + @Specialization + public RubyString expandPath(RubyString path, @SuppressWarnings("unused") UndefinedPlaceholder dir) { + return getContext().makeString(RubyFile.expandPath(path.toString())); + } + + @Specialization + public RubyString expandPath(RubyString path, RubyString dir) { + return getContext().makeString(RubyFile.expandPath(path.toString(), dir.toString())); + } + + } + + @CoreMethod(names = "file?", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class FileNode extends CoreMethodNode { + + public FileNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public FileNode(FileNode prev) { + super(prev); + } + + @Specialization + public boolean file(RubyString path) { + return new File(path.toString()).isFile(); + } + + } + + @CoreMethod(names = "join", isModuleMethod = true, needsSelf = false, isSplatted = true) + public abstract static class JoinNode extends CoreMethodNode { + + public JoinNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public JoinNode(JoinNode prev) { + super(prev); + } + + @Specialization + public RubyString join(Object[] parts) { + return getContext().makeString(RubyArray.join(parts, File.separator)); + } + } + + @CoreMethod(names = "open", isModuleMethod = true, needsSelf = false, needsBlock = true, minArgs = 2, maxArgs = 2) + public abstract static class OpenNode extends YieldingCoreMethodNode { + + public OpenNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public OpenNode(OpenNode prev) { + super(prev); + } + + @Specialization + public Object open(VirtualFrame frame, RubyString fileName, RubyString mode, RubyProc block) { + final RubyFile file = RubyFile.open(getContext(), fileName.toString(), mode.toString()); + + if (block != null) { + try { + yield(frame, block, file); + } finally { + file.close(); + } + } + + return file; + } + + } + + @CoreMethod(names = "write", maxArgs = 0) + public abstract static class WriteNode extends CoreMethodNode { + + public WriteNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public WriteNode(WriteNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder write(RubyFile file, RubyString string) { + try { + final Writer writer = file.getWriter(); + writer.write(string.toString()); + writer.flush(); + } catch (IOException e) { + throw new RuntimeException(e); + } + + return NilPlaceholder.INSTANCE; + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/FixnumNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/FixnumNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,853 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import java.math.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +@CoreClass(name = "Fixnum") +public abstract class FixnumNodes { + + @CoreMethod(names = "+@", maxArgs = 0) + public abstract static class PosNode extends CoreMethodNode { + + public PosNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public PosNode(PosNode prev) { + super(prev); + } + + @Specialization + public int pos(int value) { + return value; + } + + } + + @CoreMethod(names = "-@", maxArgs = 0) + public abstract static class NegNode extends CoreMethodNode { + + public NegNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public NegNode(NegNode prev) { + super(prev); + } + + @Specialization(rewriteOn = ArithmeticException.class) + public int neg(int value) { + return ExactMath.subtractExact(0, value); + } + + @Specialization + public BigInteger negWithOverflow(int value) { + return BigInteger.valueOf(value).negate(); + } + + } + + @CoreMethod(names = "+", minArgs = 1, maxArgs = 1) + public abstract static class AddNode extends CoreMethodNode { + + public AddNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public AddNode(AddNode prev) { + super(prev); + } + + @Specialization(rewriteOn = ArithmeticException.class) + public int add(int a, int b) { + return ExactMath.addExact(a, b); + } + + @Specialization + public Object addWithOverflow(int a, int b) { + return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).add(BigInteger.valueOf(b))); + } + + @Specialization + public double add(int a, double b) { + return a + b; + } + + @Specialization + public Object add(int a, BigInteger b) { + return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).add(b)); + } + + } + + @CoreMethod(names = "-", minArgs = 1, maxArgs = 1) + public abstract static class SubNode extends CoreMethodNode { + + public SubNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SubNode(SubNode prev) { + super(prev); + } + + @Specialization(rewriteOn = ArithmeticException.class) + public int sub(int a, int b) { + return ExactMath.subtractExact(a, b); + } + + @Specialization + public Object subWithOverflow(int a, int b) { + return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).subtract(BigInteger.valueOf(b))); + } + + @Specialization + public double sub(int a, double b) { + return a - b; + } + + @Specialization + public Object sub(int a, BigInteger b) { + return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).subtract(b)); + } + + } + + @CoreMethod(names = "*", minArgs = 1, maxArgs = 1) + public abstract static class MulNode extends CoreMethodNode { + + public MulNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public MulNode(MulNode prev) { + super(prev); + } + + @Specialization(rewriteOn = ArithmeticException.class) + public int mul(int a, int b) { + return ExactMath.multiplyExact(a, b); + } + + @Specialization + public Object mulWithOverflow(int a, int b) { + return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).multiply(BigInteger.valueOf(b))); + } + + @Specialization + public double mul(int a, double b) { + return a * b; + } + + @Specialization + public Object mul(int a, BigInteger b) { + return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).multiply(b)); + } + + } + + @CoreMethod(names = "**", minArgs = 1, maxArgs = 1) + public abstract static class PowNode extends CoreMethodNode { + + public PowNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public PowNode(PowNode prev) { + super(prev); + } + + @Specialization + public Object pow(int a, int b) { + return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).pow(b)); + } + + @Specialization + public double pow(int a, double b) { + return Math.pow(a, b); + } + + @Specialization + public Object pow(int a, BigInteger b) { + final BigInteger bigA = BigInteger.valueOf(a); + + BigInteger result = BigInteger.ONE; + + for (BigInteger n = BigInteger.ZERO; b.compareTo(b) < 0; n = n.add(BigInteger.ONE)) { + result = result.multiply(bigA); + } + + return result; + } + + } + + @CoreMethod(names = "/", minArgs = 1, maxArgs = 1) + public abstract static class DivNode extends CoreMethodNode { + + public DivNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public DivNode(DivNode prev) { + super(prev); + } + + @Specialization + public int div(int a, int b) { + return a / b; + } + + @Specialization + public double div(int a, double b) { + return a / b; + } + + @Specialization + public int div(@SuppressWarnings("unused") int a, @SuppressWarnings("unused") BigInteger b) { + return 0; + } + } + + @CoreMethod(names = "%", minArgs = 1, maxArgs = 1) + public abstract static class ModNode extends CoreMethodNode { + + public ModNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ModNode(ModNode prev) { + super(prev); + } + + @Specialization + public int mod(int a, int b) { + return a % b; + } + + @Specialization + public double mod(@SuppressWarnings("unused") int a, @SuppressWarnings("unused") double b) { + throw new UnsupportedOperationException(); + } + + @Specialization + public BigInteger mod(@SuppressWarnings("unused") int a, BigInteger b) { + return b; + } + } + + @CoreMethod(names = "divmod", minArgs = 1, maxArgs = 1) + public abstract static class DivModNode extends CoreMethodNode { + + public DivModNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public DivModNode(DivModNode prev) { + super(prev); + } + + @Specialization + public RubyArray divMod(int a, int b) { + int q; + + if (b < 0) { + if (a < 0) { + q = -a / -b; + } else { + q = -(a / -b); + } + } else { + if (a < 0) { + q = -(-a / b); + } else { + q = a / b; + } + } + + int r = a - q * b; + + if ((r < 0 && b > 0) || (r > 0 && b < 0)) { + r += b; + q -= 1; + } + + final FixnumImmutablePairArrayStore store = new FixnumImmutablePairArrayStore(q, r); + return new RubyArray(getContext().getCoreLibrary().getArrayClass(), store); + } + + @Specialization + public RubyArray divMod(@SuppressWarnings("unused") int a, @SuppressWarnings("unused") double b) { + throw new UnsupportedOperationException(); + } + + @Specialization + public RubyArray divMod(int a, BigInteger b) { + return RubyBignum.divMod(getContext(), BigInteger.valueOf(a), b); + } + } + + @CoreMethod(names = "<", minArgs = 1, maxArgs = 1) + public abstract static class LessNode extends CoreMethodNode { + + public LessNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public LessNode(LessNode prev) { + super(prev); + } + + @Specialization + public boolean less(int a, int b) { + return a < b; + } + + @Specialization + public boolean less(int a, double b) { + return a < b; + } + + @Specialization + public boolean less(int a, BigInteger b) { + return BigInteger.valueOf(a).compareTo(b) < 0; + } + } + + @CoreMethod(names = "<=", minArgs = 1, maxArgs = 1) + public abstract static class LessEqualNode extends CoreMethodNode { + + public LessEqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public LessEqualNode(LessEqualNode prev) { + super(prev); + } + + @Specialization + public boolean lessEqual(int a, int b) { + return a <= b; + } + + @Specialization + public boolean lessEqual(int a, double b) { + return a <= b; + } + + @Specialization + public boolean lessEqual(int a, BigInteger b) { + return BigInteger.valueOf(a).compareTo(b) <= 0; + } + } + + @CoreMethod(names = {"==", "==="}, minArgs = 1, maxArgs = 1) + public abstract static class EqualNode extends CoreMethodNode { + + public EqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EqualNode(EqualNode prev) { + super(prev); + } + + @Specialization + public boolean equal(int a, int b) { + return a == b; + } + + @Specialization + public boolean equal(int a, double b) { + return a == b; + } + + @Specialization + public boolean equal(int a, BigInteger b) { + return BigInteger.valueOf(a).compareTo(b) == 0; + } + } + + @CoreMethod(names = "<=>", minArgs = 1, maxArgs = 1) + public abstract static class CompareNode extends CoreMethodNode { + + public CompareNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public CompareNode(CompareNode prev) { + super(prev); + } + + @Specialization + public int compare(int a, int b) { + return Integer.compare(a, b); + } + + @Specialization + public int compare(int a, double b) { + return Double.compare(a, b); + } + + @Specialization + public int compare(int a, BigInteger b) { + return BigInteger.valueOf(a).compareTo(b); + } + } + + @CoreMethod(names = "!=", minArgs = 1, maxArgs = 1) + public abstract static class NotEqualNode extends CoreMethodNode { + + public NotEqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public NotEqualNode(NotEqualNode prev) { + super(prev); + } + + @Specialization + public boolean notEqual(int a, int b) { + return a != b; + } + + @Specialization + public boolean notEqual(int a, double b) { + return a != b; + } + + @Specialization + public boolean notEqual(int a, BigInteger b) { + return BigInteger.valueOf(a).compareTo(b) != 0; + } + } + + @CoreMethod(names = ">=", minArgs = 1, maxArgs = 1) + public abstract static class GreaterEqualNode extends CoreMethodNode { + + public GreaterEqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public GreaterEqualNode(GreaterEqualNode prev) { + super(prev); + } + + @Specialization + public boolean greaterEqual(int a, int b) { + return a >= b; + } + + @Specialization + public boolean greaterEqual(int a, double b) { + return a >= b; + } + + @Specialization + public boolean greaterEqual(int a, BigInteger b) { + return BigInteger.valueOf(a).compareTo(b) >= 0; + } + } + + @CoreMethod(names = ">", minArgs = 1, maxArgs = 1) + public abstract static class GreaterNode extends CoreMethodNode { + + public GreaterNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public GreaterNode(GreaterNode prev) { + super(prev); + } + + @Specialization + public boolean equal(int a, int b) { + return a > b; + } + + @Specialization + public boolean equal(int a, double b) { + return a > b; + } + + @Specialization + public boolean equal(int a, BigInteger b) { + return BigInteger.valueOf(a).compareTo(b) > 0; + } + } + + @CoreMethod(names = "~", maxArgs = 0) + public abstract static class ComplementNode extends CoreMethodNode { + + public ComplementNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ComplementNode(ComplementNode prev) { + super(prev); + } + + @Specialization + public int complement(int n) { + return ~n; + } + + } + + @CoreMethod(names = "&", minArgs = 1, maxArgs = 1) + public abstract static class BitAndNode extends CoreMethodNode { + + public BitAndNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public BitAndNode(BitAndNode prev) { + super(prev); + } + + @Specialization + public int bitAnd(int a, int b) { + return a & b; + } + + @Specialization + public Object bitAnd(int a, BigInteger b) { + return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).and(b)); + } + } + + @CoreMethod(names = "|", minArgs = 1, maxArgs = 1) + public abstract static class BitOrNode extends CoreMethodNode { + + public BitOrNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public BitOrNode(BitOrNode prev) { + super(prev); + } + + @Specialization + public int bitOr(int a, int b) { + return a | b; + } + + @Specialization + public Object bitOr(int a, BigInteger b) { + return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).or(b)); + } + } + + @CoreMethod(names = "^", minArgs = 1, maxArgs = 1) + public abstract static class BitXOrNode extends CoreMethodNode { + + public BitXOrNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public BitXOrNode(BitXOrNode prev) { + super(prev); + } + + @Specialization + public int bitXOr(int a, int b) { + return a ^ b; + } + + @Specialization + public Object bitXOr(int a, BigInteger b) { + return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).xor(b)); + } + } + + @CoreMethod(names = "<<", minArgs = 1, maxArgs = 1) + public abstract static class LeftShiftNode extends CoreMethodNode { + + public LeftShiftNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public LeftShiftNode(LeftShiftNode prev) { + super(prev); + } + + @Specialization + public Object leftShift(int a, int b) { + if (b > 0) { + if (RubyFixnum.SIZE - Integer.numberOfLeadingZeros(a) + b > RubyFixnum.SIZE - 1) { + return GeneralConversions.fixnumOrBignum(BigInteger.valueOf(a).shiftLeft(b)); + } else { + return a << b; + } + } else { + if (-b >= Integer.SIZE) { + return 0; + } else { + return a >> -b; + } + } + } + + } + + @CoreMethod(names = ">>", minArgs = 1, maxArgs = 1) + public abstract static class RightShiftNode extends CoreMethodNode { + + public RightShiftNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public RightShiftNode(RightShiftNode prev) { + super(prev); + } + + @Specialization + public int rightShift(int a, int b) { + if (b > 0) { + return a >> b; + } else { + if (-b >= RubyFixnum.SIZE) { + return 0; + } else { + return a >> -b; + } + } + } + + } + + @CoreMethod(names = "[]", minArgs = 1, maxArgs = 1) + public abstract static class GetIndexNode extends CoreMethodNode { + + public GetIndexNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public GetIndexNode(GetIndexNode prev) { + super(prev); + } + + @Specialization + public int getIndex(int self, int index) { + if ((self & (1 << index)) == 0) { + return 0; + } else { + return 1; + } + } + + } + + @CoreMethod(names = "chr", maxArgs = 0) + public abstract static class ChrNode extends CoreMethodNode { + + public ChrNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ChrNode(ChrNode prev) { + super(prev); + } + + @Specialization + public RubyString chr(int n) { + // TODO(CS): not sure about encoding here + return getContext().makeString((char) n); + } + + } + + @CoreMethod(names = "inspect", maxArgs = 0) + public abstract static class InpsectNode extends CoreMethodNode { + + public InpsectNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InpsectNode(InpsectNode prev) { + super(prev); + } + + @Specialization + public RubyString inspect(int n) { + return getContext().makeString(Integer.toString(n)); + } + + } + + @CoreMethod(names = "nonzero?", maxArgs = 0) + public abstract static class NonZeroNode extends CoreMethodNode { + + public NonZeroNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public NonZeroNode(NonZeroNode prev) { + super(prev); + } + + @Specialization + public Object nonZero(int value) { + if (value == 0) { + return false; + } else { + return value; + } + } + + } + + @CoreMethod(names = "size", needsSelf = false, maxArgs = 0) + public abstract static class SizeNode extends CoreMethodNode { + + public SizeNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SizeNode(SizeNode prev) { + super(prev); + } + + @Specialization + public int size() { + return Integer.SIZE / Byte.SIZE; + } + + } + + @CoreMethod(names = "step", needsBlock = true, minArgs = 2, maxArgs = 2) + public abstract static class StepNode extends YieldingCoreMethodNode { + + public StepNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public StepNode(StepNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder step(VirtualFrame frame, int from, int to, int step, RubyProc block) { + for (int i = from; i <= to; i += step) { + yield(frame, block, i); + } + + return NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = "times", needsBlock = true, maxArgs = 0) + public abstract static class TimesNode extends YieldingCoreMethodNode { + + public TimesNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public TimesNode(TimesNode prev) { + super(prev); + } + + @Specialization + public int times(VirtualFrame frame, int n, RubyProc block) { + for (int i = 0; i < n; i++) { + yield(frame, block, i); + } + + return n; + } + + } + + @CoreMethod(names = {"to_i", "to_int"}, maxArgs = 0) + public abstract static class ToINode extends CoreMethodNode { + + public ToINode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToINode(ToINode prev) { + super(prev); + } + + @Specialization + public int toI(int n) { + return n; + } + + } + + @CoreMethod(names = "to_f", maxArgs = 0) + public abstract static class ToFNode extends CoreMethodNode { + + public ToFNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToFNode(ToFNode prev) { + super(prev); + } + + @Specialization + public double toF(int n) { + return n; + } + + } + + @CoreMethod(names = "to_s", maxArgs = 0) + public abstract static class ToSNode extends CoreMethodNode { + + public ToSNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToSNode(ToSNode prev) { + super(prev); + } + + @Specialization + public RubyString toS(int n) { + return getContext().makeString(Integer.toString(n)); + } + + } + + @CoreMethod(names = "upto", needsBlock = true, minArgs = 1, maxArgs = 1) + public abstract static class UpToNode extends YieldingCoreMethodNode { + + public UpToNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public UpToNode(UpToNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder upto(VirtualFrame frame, int from, int to, RubyProc block) { + for (int i = from; i <= to; i++) { + yield(frame, block, i); + } + + return NilPlaceholder.INSTANCE; + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/FloatNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/FloatNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,493 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import java.math.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +@CoreClass(name = "Float") +public abstract class FloatNodes { + + @CoreMethod(names = "+@", maxArgs = 0) + public abstract static class PosNode extends CoreMethodNode { + + public PosNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public PosNode(PosNode prev) { + super(prev); + } + + @Specialization + public double pos(double value) { + return value; + } + + } + + @CoreMethod(names = "-@", maxArgs = 0) + public abstract static class NegNode extends CoreMethodNode { + + public NegNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public NegNode(NegNode prev) { + super(prev); + } + + @Specialization + public double neg(double value) { + return -value; + } + + } + + @CoreMethod(names = "+", minArgs = 1, maxArgs = 1) + public abstract static class AddNode extends CoreMethodNode { + + public AddNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public AddNode(AddNode prev) { + super(prev); + } + + @Specialization + public double add(double a, int b) { + return a + b; + } + + @Specialization + public double add(double a, double b) { + return a + b; + } + + @Specialization + public double add(double a, BigInteger b) { + return a + b.doubleValue(); + } + + } + + @CoreMethod(names = "-", minArgs = 1, maxArgs = 1) + public abstract static class SubNode extends CoreMethodNode { + + public SubNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SubNode(SubNode prev) { + super(prev); + } + + @Specialization + public double sub(double a, int b) { + return a - b; + } + + @Specialization + public double sub(double a, double b) { + return a - b; + } + + @Specialization + public double sub(double a, BigInteger b) { + return a - b.doubleValue(); + } + + } + + @CoreMethod(names = "*", minArgs = 1, maxArgs = 1) + public abstract static class MulNode extends CoreMethodNode { + + public MulNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public MulNode(MulNode prev) { + super(prev); + } + + @Specialization + public double mul(double a, int b) { + return a * b; + } + + @Specialization + public double mul(double a, double b) { + return a * b; + } + + @Specialization + public double mul(double a, BigInteger b) { + return a * b.doubleValue(); + } + + } + + @CoreMethod(names = "**", minArgs = 1, maxArgs = 1) + public abstract static class PowNode extends CoreMethodNode { + + public PowNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public PowNode(PowNode prev) { + super(prev); + } + + @Specialization + public double mul(double a, int b) { + return Math.pow(a, b); + } + + @Specialization + public double mul(double a, double b) { + return Math.pow(a, b); + } + + @Specialization + public double mul(double a, BigInteger b) { + return Math.pow(a, b.doubleValue()); + } + + } + + @CoreMethod(names = "/", minArgs = 1, maxArgs = 1) + public abstract static class DivNode extends CoreMethodNode { + + public DivNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public DivNode(DivNode prev) { + super(prev); + } + + @Specialization + public double div(double a, int b) { + return a / b; + } + + @Specialization + public double div(double a, double b) { + return a / b; + } + + @Specialization + public double div(double a, BigInteger b) { + return a / b.doubleValue(); + } + + } + + @CoreMethod(names = "%", minArgs = 1, maxArgs = 1) + public abstract static class ModNode extends CoreMethodNode { + + public ModNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ModNode(ModNode prev) { + super(prev); + } + + @Specialization + public double mod(@SuppressWarnings("unused") double a, @SuppressWarnings("unused") int b) { + throw new UnsupportedOperationException(); + } + + @Specialization + public double mod(@SuppressWarnings("unused") double a, @SuppressWarnings("unused") double b) { + throw new UnsupportedOperationException(); + } + + @Specialization + public double mod(@SuppressWarnings("unused") double a, @SuppressWarnings("unused") BigInteger b) { + throw new UnsupportedOperationException(); + } + + } + + @CoreMethod(names = "divmod", minArgs = 1, maxArgs = 1) + public abstract static class DivModNode extends CoreMethodNode { + + public DivModNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public DivModNode(DivModNode prev) { + super(prev); + } + + @Specialization + public RubyArray divMod(@SuppressWarnings("unused") double a, @SuppressWarnings("unused") int b) { + throw new UnsupportedOperationException(); + } + + @Specialization + public RubyArray divMod(@SuppressWarnings("unused") double a, @SuppressWarnings("unused") double b) { + throw new UnsupportedOperationException(); + } + + @Specialization + public RubyArray divMod(@SuppressWarnings("unused") double a, @SuppressWarnings("unused") BigInteger b) { + throw new UnsupportedOperationException(); + } + + } + + @CoreMethod(names = "<", minArgs = 1, maxArgs = 1) + public abstract static class LessNode extends CoreMethodNode { + + public LessNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public LessNode(LessNode prev) { + super(prev); + } + + @Specialization + public boolean less(double a, int b) { + return a < b; + } + + @Specialization + public boolean less(double a, double b) { + return a < b; + } + + @Specialization + public boolean less(double a, BigInteger b) { + return BigInteger.valueOf((long) a).compareTo(b) < 0; + } + } + + @CoreMethod(names = "<=", minArgs = 1, maxArgs = 1) + public abstract static class LessEqualNode extends CoreMethodNode { + + public LessEqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public LessEqualNode(LessEqualNode prev) { + super(prev); + } + + @Specialization + public boolean lessEqual(double a, int b) { + return a <= b; + } + + @Specialization + public boolean lessEqual(double a, double b) { + return a <= b; + } + + @Specialization + public boolean lessEqual(double a, BigInteger b) { + return BigInteger.valueOf((long) a).compareTo(b) <= 0; + } + } + + @CoreMethod(names = "==", minArgs = 1, maxArgs = 1) + public abstract static class EqualNode extends CoreMethodNode { + + public EqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EqualNode(EqualNode prev) { + super(prev); + } + + @Specialization + public boolean equal(double a, int b) { + return a == b; + } + + @Specialization + public boolean equal(double a, double b) { + return a == b; + } + + @Specialization + public boolean equal(double a, BigInteger b) { + return BigInteger.valueOf((long) a).compareTo(b) == 0; + } + } + + @CoreMethod(names = "!=", minArgs = 1, maxArgs = 1) + public abstract static class NotEqualNode extends CoreMethodNode { + + public NotEqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public NotEqualNode(NotEqualNode prev) { + super(prev); + } + + @Specialization + public boolean notEqual(double a, int b) { + return a != b; + } + + @Specialization + public boolean notEqual(double a, double b) { + return a != b; + } + + @Specialization + public boolean notEqual(double a, BigInteger b) { + return BigInteger.valueOf((long) a).compareTo(b) != 0; + } + } + + @CoreMethod(names = ">=", minArgs = 1, maxArgs = 1) + public abstract static class GreaterEqualNode extends CoreMethodNode { + + public GreaterEqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public GreaterEqualNode(GreaterEqualNode prev) { + super(prev); + } + + @Specialization + public boolean greaterEqual(double a, int b) { + return a >= b; + } + + @Specialization + public boolean greaterEqual(double a, double b) { + return a >= b; + } + + @Specialization + public boolean greaterEqual(double a, BigInteger b) { + return BigInteger.valueOf((long) a).compareTo(b) >= 0; + } + } + + @CoreMethod(names = ">", minArgs = 1, maxArgs = 1) + public abstract static class GreaterNode extends CoreMethodNode { + + public GreaterNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public GreaterNode(GreaterNode prev) { + super(prev); + } + + @Specialization + public boolean equal(double a, int b) { + return a > b; + } + + @Specialization + public boolean equal(double a, double b) { + return a > b; + } + + @Specialization + public boolean equal(double a, BigInteger b) { + return BigInteger.valueOf((long) a).compareTo(b) > 0; + } + } + + @CoreMethod(names = "abs", maxArgs = 0) + public abstract static class AbsNode extends CoreMethodNode { + + public AbsNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public AbsNode(AbsNode prev) { + super(prev); + } + + @Specialization + public double abs(double n) { + return Math.abs(n); + } + + } + + @CoreMethod(names = "inspect", maxArgs = 0) + public abstract static class InpsectNode extends CoreMethodNode { + + public InpsectNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InpsectNode(InpsectNode prev) { + super(prev); + } + + @Specialization + public RubyString inspect(double n) { + return getContext().makeString(Double.toString(n)); + } + + } + + @CoreMethod(names = "nonzero?", maxArgs = 0) + public abstract static class NonZeroNode extends CoreMethodNode { + + public NonZeroNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public NonZeroNode(NonZeroNode prev) { + super(prev); + } + + @Specialization + public Object nonZero(double value) { + if (value == 0) { + return false; + } else { + return value; + } + } + + } + + @CoreMethod(names = "to_s", maxArgs = 0) + public abstract static class ToSNode extends CoreMethodNode { + + public ToSNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToSNode(ToSNode prev) { + super(prev); + } + + @Specialization + public RubyString toS(double value) { + return getContext().makeString(Double.toString(value)); + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/HashNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/HashNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +@CoreClass(name = "Hash") +public abstract class HashNodes { + + @CoreMethod(names = "[]", isModuleMethod = true, needsSelf = false, isSplatted = true) + public abstract static class ConstructNode extends CoreMethodNode { + + public ConstructNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ConstructNode(ConstructNode prev) { + super(prev); + } + + @Specialization + public RubyHash construct(Object[] args) { + final RubyHash hash = new RubyHash(getContext().getCoreLibrary().getHashClass()); + + if (args.length == 1) { + final RubyArray array = (RubyArray) args[0]; + + for (int n = 0; n < array.size(); n++) { + final RubyArray keyValue = (RubyArray) array.get(n); + hash.put(keyValue.get(0), keyValue.get(1)); + } + } else { + assert args.length % 2 == 0; + + for (int n = 0; n < args.length; n += 2) { + hash.put(args[n], args[n + 1]); + } + } + + return hash; + } + + } + + @CoreMethod(names = "[]", minArgs = 1, maxArgs = 1) + public abstract static class GetIndexNode extends CoreMethodNode { + + public GetIndexNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public GetIndexNode(GetIndexNode prev) { + super(prev); + } + + @Specialization + public Object construct(VirtualFrame frame, RubyHash hash, Object index) { + final Object value = hash.get(index); + + if (value == null) { + if (hash.defaultBlock == null) { + return NilPlaceholder.INSTANCE; + } else { + return hash.defaultBlock.call(frame.pack(), hash, index); + } + } else { + return value; + } + } + + } + + @CoreMethod(names = "[]=", minArgs = 2, maxArgs = 2) + public abstract static class SetIndexNode extends CoreMethodNode { + + public SetIndexNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SetIndexNode(SetIndexNode prev) { + super(prev); + } + + @Specialization + public Object construct(RubyHash hash, Object index, Object value) { + hash.put(index, value); + return value; + } + + } + + @CoreMethod(names = "delete", minArgs = 1, maxArgs = 1) + public abstract static class DeleteNode extends CoreMethodNode { + + public DeleteNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public DeleteNode(DeleteNode prev) { + super(prev); + } + + @Specialization + public Object delete(RubyHash hash, Object index) { + hash.checkFrozen(); + + final Object value = hash.getMap().remove(index); + + if (value == null) { + return NilPlaceholder.INSTANCE; + } else { + return value; + } + } + + } + + @CoreMethod(names = "each", needsBlock = true, maxArgs = 0) + public abstract static class EachNode extends YieldingCoreMethodNode { + + public EachNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EachNode(EachNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder each(VirtualFrame frame, RubyHash hash, RubyProc block) { + for (Map.Entry entry : hash.storage.entrySet()) { + yield(frame, block, entry.getKey(), entry.getValue()); + } + + return NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = "empty?", maxArgs = 0) + public abstract static class EmptyNode extends CoreMethodNode { + + public EmptyNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EmptyNode(EmptyNode prev) { + super(prev); + } + + @Specialization + public boolean empty(RubyHash hash) { + return hash.storage.isEmpty(); + } + + } + + @CoreMethod(names = "initialize", needsBlock = true, maxArgs = 0) + public abstract static class InitializeNode extends CoreMethodNode { + + public InitializeNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InitializeNode(InitializeNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder initialize(RubyHash hash, @SuppressWarnings("unused") UndefinedPlaceholder block) { + hash.initialize(null); + return NilPlaceholder.INSTANCE; + } + + @Specialization + public NilPlaceholder initialize(RubyHash hash, RubyProc block) { + hash.initialize(block); + return NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = {"map", "collect"}, needsBlock = true, maxArgs = 0) + public abstract static class MapNode extends YieldingCoreMethodNode { + + public MapNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public MapNode(MapNode prev) { + super(prev); + } + + @Specialization + public RubyArray map(VirtualFrame frame, RubyHash hash, RubyProc block) { + final RubyArray result = new RubyArray(getContext().getCoreLibrary().getArrayClass()); + + for (Map.Entry entry : hash.storage.entrySet()) { + result.push(yield(frame, block, entry.getKey(), entry.getValue())); + } + + return result; + } + + } + + @CoreMethod(names = "key?", minArgs = 1, maxArgs = 1) + public abstract static class KeyNode extends CoreMethodNode { + + public KeyNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public KeyNode(KeyNode prev) { + super(prev); + } + + @Specialization + public boolean key(RubyHash hash, Object key) { + return hash.storage.containsKey(key); + } + + } + + @CoreMethod(names = "keys", maxArgs = 0) + public abstract static class KeysNode extends CoreMethodNode { + + public KeysNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public KeysNode(KeysNode prev) { + super(prev); + } + + @Specialization + public RubyArray keys(RubyHash hash) { + final RubyArray array = new RubyArray(getContext().getCoreLibrary().getArrayClass()); + + for (Object key : hash.storage.keySet()) { + array.push(key); + } + + return array; + } + + } + + @CoreMethod(names = "size", maxArgs = 0) + public abstract static class SizeNode extends CoreMethodNode { + + public SizeNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SizeNode(SizeNode prev) { + super(prev); + } + + @Specialization + public int size(RubyHash hash) { + return hash.storage.size(); + } + + } + + @CoreMethod(names = "values", maxArgs = 0) + public abstract static class ValuesNode extends CoreMethodNode { + + public ValuesNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ValuesNode(ValuesNode prev) { + super(prev); + } + + @Specialization + public RubyArray values(RubyHash hash) { + final RubyArray array = new RubyArray(getContext().getCoreLibrary().getArrayClass()); + + for (Object value : hash.storage.values()) { + array.push(value); + } + + return array; + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/InterpolatedStringNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/InterpolatedStringNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * A list of expressions to build up into a string. + */ +@NodeInfo(shortName = "interpolated-string") +public final class InterpolatedStringNode extends RubyNode { + + @CompilationFinal private int expectedLength = 64; + + @Children protected final RubyNode[] children; + + public InterpolatedStringNode(RubyContext context, SourceSection sourceSection, RubyNode[] children) { + super(context, sourceSection); + this.children = adoptChildren(children); + } + + @ExplodeLoop + @Override + public Object execute(VirtualFrame frame) { + final StringBuilder builder = new StringBuilder(expectedLength); + + for (int n = 0; n < children.length; n++) { + builder.append(children[n].execute(frame).toString()); + } + + if (builder.length() > expectedLength) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + expectedLength = builder.length() * 2; + } + + return getContext().makeString(builder.toString()); + } + + @ExplodeLoop + @Override + public void executeVoid(VirtualFrame frame) { + for (int n = 0; n < children.length; n++) { + children[n].executeVoid(frame); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/KernelNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/KernelNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,823 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import java.io.*; +import java.math.*; +import java.util.*; + +import com.oracle.truffle.api.CompilerDirectives.SlowPath; +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.nodes.call.*; +import com.oracle.truffle.ruby.nodes.cast.*; +import com.oracle.truffle.ruby.nodes.control.*; +import com.oracle.truffle.ruby.nodes.literal.*; +import com.oracle.truffle.ruby.nodes.yield.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.configuration.*; +import com.oracle.truffle.ruby.runtime.control.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; +import com.oracle.truffle.ruby.runtime.objects.*; +import com.oracle.truffle.ruby.runtime.subsystems.*; + +@CoreClass(name = "Kernel") +public abstract class KernelNodes { + + @CoreMethod(names = "Array", isModuleMethod = true, needsSelf = false, isSplatted = true) + public abstract static class ArrayNode extends CoreMethodNode { + + public ArrayNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ArrayNode(ArrayNode prev) { + super(prev); + } + + @Specialization + public RubyArray array(Object[] args) { + if (args.length == 1 && args[0] instanceof RubyArray) { + return (RubyArray) args[0]; + } else { + return RubyArray.specializedFromObjects(getContext().getCoreLibrary().getArrayClass(), args); + } + } + + } + + @CoreMethod(names = "at_exit", isModuleMethod = true, needsSelf = false, needsBlock = true, maxArgs = 0) + public abstract static class AtExitNode extends CoreMethodNode { + + public AtExitNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public AtExitNode(AtExitNode prev) { + super(prev); + } + + @Specialization + public Object atExit(RubyProc block) { + getContext().getAtExitManager().add(block); + return NilPlaceholder.INSTANCE; + } + } + + @CoreMethod(names = "binding", isModuleMethod = true, needsSelf = true, maxArgs = 0) + public abstract static class BindingNode extends CoreMethodNode { + + public BindingNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public BindingNode(BindingNode prev) { + super(prev); + } + + @Specialization + public Object binding(VirtualFrame frame, Object self) { + return new RubyBinding(getContext().getCoreLibrary().getBindingClass(), self, frame.getCaller().unpack().materialize()); + } + } + + @CoreMethod(names = "block_given?", isModuleMethod = true, needsSelf = false, maxArgs = 0) + public abstract static class BlockGivenNode extends CoreMethodNode { + + public BlockGivenNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public BlockGivenNode(BlockGivenNode prev) { + super(prev); + } + + @Specialization + public boolean blockGiven(VirtualFrame frame) { + return frame.getCaller().unpack().getArguments(RubyArguments.class).getBlock() != null; + } + } + + // TODO(CS): should hide this in a feature + + @CoreMethod(names = "callcc", isModuleMethod = true, needsSelf = false, needsBlock = true, maxArgs = 0) + public abstract static class CallccNode extends CoreMethodNode { + + public CallccNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public CallccNode(CallccNode prev) { + super(prev); + } + + @Specialization + public Object callcc(RubyProc block) { + final RubyContext context = getContext(); + + if (block == null) { + // TODO(CS): should really have acceptsBlock and needsBlock to do this automatically + throw new RaiseException(context.getCoreLibrary().localJumpError("no block given")); + } + + final RubyContinuation continuation = new RubyContinuation(context.getCoreLibrary().getContinuationClass()); + return continuation.enter(block); + } + } + + @CoreMethod(names = "catch", isModuleMethod = true, needsSelf = false, needsBlock = true, minArgs = 1, maxArgs = 1) + public abstract static class CatchNode extends YieldingCoreMethodNode { + + public CatchNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public CatchNode(CatchNode prev) { + super(prev); + } + + @Specialization + public Object doCatch(VirtualFrame frame, Object tag, RubyProc block) { + try { + return yield(frame, block); + } catch (ThrowException e) { + if (e.getTag().equals(tag)) { + // TODO(cs): unset rather than set to Nil? + getContext().getCoreLibrary().getGlobalVariablesObject().setInstanceVariable("$!", NilPlaceholder.INSTANCE); + return e.getValue(); + } else { + throw e; + } + } + } + } + + @CoreMethod(names = "eval", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 2) + public abstract static class EvalNode extends CoreMethodNode { + + public EvalNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EvalNode(EvalNode prev) { + super(prev); + } + + @Specialization + public Object eval(RubyString source, @SuppressWarnings("unused") UndefinedPlaceholder binding) { + return getContext().eval(source.toString()); + } + + @Specialization + public Object eval(RubyString source, RubyBinding binding) { + return getContext().eval(source.toString(), binding); + } + + } + + @CoreMethod(names = "exec", isModuleMethod = true, needsSelf = false, minArgs = 1, isSplatted = true) + public abstract static class ExecNode extends CoreMethodNode { + + public ExecNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ExecNode(ExecNode prev) { + super(prev); + } + + @Specialization + public Object require(Object[] args) { + final String[] commandLine = new String[args.length]; + + for (int n = 0; n < args.length; n++) { + commandLine[n] = args[n].toString(); + } + + exec(getContext(), commandLine); + + return null; + } + + @SlowPath + private static void exec(RubyContext context, String[] commandLine) { + context.implementationMessage("starting child process to simulate exec: "); + + for (int n = 0; n < commandLine.length; n++) { + if (n > 0) { + System.err.print(" "); + } + + System.err.print(commandLine[n]); + } + + final ProcessBuilder builder = new ProcessBuilder(commandLine); + builder.inheritIO(); + + final RubyHash env = (RubyHash) context.getCoreLibrary().getObjectClass().lookupConstant("ENV"); + + for (Map.Entry entry : env.getMap().entrySet()) { + builder.environment().put(entry.getKey().toString(), entry.getValue().toString()); + } + + Process process; + + try { + process = builder.start(); + } catch (IOException e) { + // TODO(cs): proper Ruby exception + throw new RuntimeException(e); + } + + int exitCode; + + while (true) { + try { + exitCode = process.waitFor(); + break; + } catch (InterruptedException e) { + continue; + } + } + + context.implementationMessage("child process simulating exec finished"); + + System.exit(exitCode); + } + + } + + @CoreMethod(names = "exit", isModuleMethod = true, needsSelf = false, minArgs = 0, maxArgs = 1) + public abstract static class ExitNode extends CoreMethodNode { + + public ExitNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ExitNode(ExitNode prev) { + super(prev); + } + + @Specialization + public Object exit(@SuppressWarnings("unused") UndefinedPlaceholder exitCode) { + getContext().shutdown(); + System.exit(0); + return null; + } + + @Specialization + public Object exit(int exitCode) { + getContext().shutdown(); + System.exit(exitCode); + return null; + } + + } + + @CoreMethod(names = "gets", isModuleMethod = true, needsSelf = false, maxArgs = 0) + public abstract static class GetsNode extends CoreMethodNode { + + public GetsNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public GetsNode(GetsNode prev) { + super(prev); + } + + @Specialization + public RubyString gets(VirtualFrame frame) { + final RubyContext context = getContext(); + + final ThreadManager threadManager = context.getThreadManager(); + + RubyString line; + + try { + final RubyThread runningThread = threadManager.leaveGlobalLock(); + + try { + line = context.makeString(context.getConfiguration().getInputReader().readLine("")); + } finally { + threadManager.enterGlobalLock(runningThread); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + + // Set the local variable $_ in the caller + + final Frame unpacked = frame.getCaller().unpack(); + final FrameSlot slot = unpacked.getFrameDescriptor().findFrameSlot("$_"); + + if (slot != null) { + unpacked.setObject(slot, line); + } + + return line; + } + } + + @CoreMethod(names = "Integer", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class IntegerNode extends CoreMethodNode { + + @Child protected DispatchHeadNode toInt; + + public IntegerNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + toInt = adoptChild(new DispatchHeadNode(context, getSourceSection(), "to_int", false)); + } + + public IntegerNode(IntegerNode prev) { + super(prev); + toInt = adoptChild(prev.toInt); + } + + @Specialization + public int integer(int value) { + return value; + } + + @Specialization + public BigInteger integer(BigInteger value) { + return value; + } + + @Specialization + public int integer(double value) { + return (int) value; + } + + @Specialization + public Object integer(RubyString value) { + return value.toInteger(); + } + + @Specialization + public Object integer(VirtualFrame frame, Object value) { + return toInt.dispatch(frame, value, null); + } + + } + + @CoreMethod(names = "lambda", isModuleMethod = true, needsBlock = true, maxArgs = 0) + public abstract static class LambdaNode extends CoreMethodNode { + + public LambdaNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public LambdaNode(LambdaNode prev) { + super(prev); + } + + @Specialization + public RubyProc proc(Object self, RubyProc block) { + return new RubyProc(getContext().getCoreLibrary().getProcClass(), RubyProc.Type.LAMBDA, self, block, block.getMethod()); + + } + } + + @CoreMethod(names = "load", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class LoadNode extends CoreMethodNode { + + public LoadNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public LoadNode(LoadNode prev) { + super(prev); + } + + @Specialization + public boolean load(RubyString file) { + getContext().loadFile(file.toString()); + return true; + } + } + + @CoreMethod(names = "loop", isModuleMethod = true, needsSelf = false, maxArgs = 0) + public abstract static class LoopNode extends CoreMethodNode { + + @Child protected WhileNode whileNode; + + public LoopNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + whileNode = adoptChild(new WhileNode(context, sourceSection, BooleanCastNodeFactory.create(context, sourceSection, new BooleanLiteralNode(context, sourceSection, true)), new YieldNode( + context, getSourceSection(), new RubyNode[]{}))); + } + + public LoopNode(LoopNode prev) { + super(prev); + whileNode = adoptChild(prev.whileNode); + } + + @Specialization + public Object loop(VirtualFrame frame) { + return whileNode.execute(frame); + } + } + + @CoreMethod(names = "print", isModuleMethod = true, needsSelf = false, isSplatted = true) + public abstract static class PrintNode extends CoreMethodNode { + + public PrintNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public PrintNode(PrintNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder print(Object[] args) { + final RubyContext context = getContext(); + final ThreadManager threadManager = context.getThreadManager(); + + final RubyThread runningThread = threadManager.leaveGlobalLock(); + + try { + for (Object arg : args) { + /* + * TODO(cs): If it's a RubyString and made up of bytes, just write the bytes out + * - using toString will mess up the encoding. We need to stop using toString + * everywhere, and write our own bytes, possibly using JRuby's library for this. + */ + + if (arg instanceof RubyString && !((RubyString) arg).isFromJavaString()) { + try { + context.getConfiguration().getStandardOut().write(((RubyString) arg).getBytes()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } else { + context.getConfiguration().getStandardOut().print(arg); + } + } + } finally { + threadManager.enterGlobalLock(runningThread); + } + + return NilPlaceholder.INSTANCE; + } + } + + @CoreMethod(names = "printf", isModuleMethod = true, needsSelf = false, isSplatted = true) + public abstract static class PrintfNode extends CoreMethodNode { + + public PrintfNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public PrintfNode(PrintfNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder printf(Object[] args) { + final RubyContext context = getContext(); + final ThreadManager threadManager = context.getThreadManager(); + + if (args.length > 0) { + final String format = ((RubyString) args[0]).toString(); + final List values = Arrays.asList(args).subList(1, args.length); + + final RubyThread runningThread = threadManager.leaveGlobalLock(); + + try { + StringFormatter.format(context.getConfiguration().getStandardOut(), format, values); + } finally { + threadManager.enterGlobalLock(runningThread); + } + } + + return NilPlaceholder.INSTANCE; + } + } + + /* + * Kernel#pretty_inspect is normally part of stdlib, in pp.rb, but we aren't able to execute + * that file yet. Instead we implement a very simple version here, which is the solution + * suggested by RubySpec. + */ + + @CoreMethod(names = "pretty_inspect", maxArgs = 0) + public abstract static class PrettyInspectNode extends CoreMethodNode { + + @Child protected DispatchHeadNode toS; + + public PrettyInspectNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + toS = adoptChild(new DispatchHeadNode(context, getSourceSection(), "to_s", false)); + } + + public PrettyInspectNode(PrettyInspectNode prev) { + super(prev); + toS = adoptChild(prev.toS); + } + + @Specialization + public Object prettyInspect(VirtualFrame frame, Object self) { + return toS.dispatch(frame, self, null); + + } + } + + @CoreMethod(names = "proc", isModuleMethod = true, needsBlock = true, maxArgs = 0, versions = RubyVersion.RUBY_18) + public abstract static class Proc18Node extends CoreMethodNode { + + public Proc18Node(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public Proc18Node(Proc18Node prev) { + super(prev); + } + + @Specialization + public RubyProc proc(Object self, RubyProc block) { + return new RubyProc(getContext().getCoreLibrary().getProcClass(), RubyProc.Type.LAMBDA, self, block, block.getMethod()); + + } + } + + @CoreMethod(names = "proc", isModuleMethod = true, needsBlock = true, maxArgs = 0, versions = {RubyVersion.RUBY_19, RubyVersion.RUBY_20, RubyVersion.RUBY_21}) + public abstract static class ProcNode extends CoreMethodNode { + + public ProcNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ProcNode(ProcNode prev) { + super(prev); + } + + @Specialization + public RubyProc proc(Object self, RubyProc block) { + return new RubyProc(getContext().getCoreLibrary().getProcClass(), RubyProc.Type.PROC, self, block, block.getMethod()); + + } + } + + @CoreMethod(names = "puts", isModuleMethod = true, needsSelf = false, isSplatted = true) + public abstract static class PutsNode extends CoreMethodNode { + + public PutsNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public PutsNode(PutsNode prev) { + super(prev); + } + + @ExplodeLoop + @Specialization + public NilPlaceholder puts(Object[] args) { + final RubyContext context = getContext(); + final ThreadManager threadManager = context.getThreadManager(); + final PrintStream standardOut = context.getConfiguration().getStandardOut(); + + final RubyThread runningThread = threadManager.leaveGlobalLock(); + + try { + if (args.length == 0) { + standardOut.println(); + } else { + for (int n = 0; n < args.length; n++) { + puts(context, standardOut, args[n]); + } + } + } finally { + threadManager.enterGlobalLock(runningThread); + } + + return NilPlaceholder.INSTANCE; + } + + @SlowPath + private void puts(RubyContext context, PrintStream standardOut, Object value) { + if (value instanceof RubyArray) { + final RubyArray array = (RubyArray) value; + + for (int n = 0; n < array.size(); n++) { + puts(context, standardOut, array.get(n)); + } + } else { + // TODO(CS): slow path send + standardOut.println(context.getCoreLibrary().box(value).send("to_s", null)); + } + } + + } + + @CoreMethod(names = "raise", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 2) + public abstract static class RaiseNode extends CoreMethodNode { + + @Child protected DispatchHeadNode initialize; + + public RaiseNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + initialize = adoptChild(new DispatchHeadNode(context, getSourceSection(), "initialize", false)); + } + + public RaiseNode(RaiseNode prev) { + super(prev); + initialize = adoptChild(prev.initialize); + } + + @Specialization(order = 1) + public Object raise(VirtualFrame frame, RubyString message, @SuppressWarnings("unused") UndefinedPlaceholder undefined) { + return raise(frame, getContext().getCoreLibrary().getRuntimeErrorClass(), message); + } + + @Specialization(order = 2) + public Object raise(VirtualFrame frame, RubyClass exceptionClass, @SuppressWarnings("unused") UndefinedPlaceholder undefined) { + return raise(frame, exceptionClass, getContext().makeString("")); + } + + @Specialization(order = 3) + public Object raise(VirtualFrame frame, RubyClass exceptionClass, RubyString message) { + final RubyContext context = getContext(); + + if (context.getConfiguration().getPrintRubyExceptions()) { + context.implementationMessage("Ruby raise: %s", message); + new Exception().printStackTrace(); + } + + final RubyBasicObject exception = exceptionClass.newInstance(); + initialize.dispatch(frame, exception, null, message); + throw new RaiseException(exception); + } + + } + + @CoreMethod(names = "require", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class RequireNode extends CoreMethodNode { + + public RequireNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public RequireNode(RequireNode prev) { + super(prev); + } + + @Specialization + public boolean require(RubyString feature) { + try { + getContext().getFeatureManager().require(feature.toString()); + } catch (IOException e) { + throw new RuntimeException(e); + } + + return true; + } + } + + @CoreMethod(names = "set_trace_func", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class SetTraceFuncNode extends CoreMethodNode { + + public SetTraceFuncNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SetTraceFuncNode(SetTraceFuncNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder setTraceFunc(NilPlaceholder proc) { + getContext().getTraceManager().setTraceProc(null); + return proc; + } + + @Specialization + public RubyProc setTraceFunc(RubyProc proc) { + getContext().getTraceManager().setTraceProc(proc); + return proc; + } + + } + + @CoreMethod(names = "String", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class StringNode extends CoreMethodNode { + + @Child protected DispatchHeadNode toS; + + public StringNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + toS = adoptChild(new DispatchHeadNode(context, getSourceSection(), "to_s", false)); + } + + public StringNode(StringNode prev) { + super(prev); + toS = adoptChild(prev.toS); + } + + @Specialization + public RubyString string(int value) { + return getContext().makeString(Integer.toString(value)); + } + + @Specialization + public RubyString string(BigInteger value) { + return getContext().makeString(value.toString()); + } + + @Specialization + public RubyString string(double value) { + return getContext().makeString(Double.toString(value)); + } + + @Specialization + public RubyString string(RubyString value) { + return value; + } + + @Specialization + public Object string(VirtualFrame frame, Object value) { + return toS.dispatch(frame, value, null); + } + + } + + @CoreMethod(names = "sleep", isModuleMethod = true, needsSelf = false, maxArgs = 1) + public abstract static class SleepNode extends CoreMethodNode { + + public SleepNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SleepNode(SleepNode prev) { + super(prev); + } + + @Specialization + public double sleep(double duration) { + final RubyContext context = getContext(); + + final RubyThread runningThread = context.getThreadManager().leaveGlobalLock(); + + try { + final long start = System.nanoTime(); + + try { + Thread.sleep((long) (duration * 1000)); + } catch (InterruptedException e) { + // Ignore interruption + } + + final long end = System.nanoTime(); + + return (end - start) / 1e9; + } finally { + context.getThreadManager().enterGlobalLock(runningThread); + } + } + + @Specialization + public double sleep(int duration) { + return sleep((double) duration); + } + + } + + @CoreMethod(names = "throw", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 2) + public abstract static class ThrowNode extends CoreMethodNode { + + public ThrowNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ThrowNode(ThrowNode prev) { + super(prev); + } + + @Specialization + public Object doThrow(Object tag, UndefinedPlaceholder value) { + return doThrow(tag, (Object) value); + } + + @Specialization + public Object doThrow(Object tag, Object value) { + if (value instanceof UndefinedPlaceholder) { + throw new ThrowException(tag, NilPlaceholder.INSTANCE); + } else { + throw new ThrowException(tag, value); + } + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/MainNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/MainNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +@CoreClass(name = "main") +public abstract class MainNodes { + + @CoreMethod(names = "include", isSplatted = true, minArgs = 1) + public abstract static class IncludeNode extends CoreMethodNode { + + public IncludeNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public IncludeNode(IncludeNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder include(RubyObject main, Object[] args) { + // TODO(cs): copied from Module - but where does this method really come from? + + // Note that we traverse the arguments backwards + + for (int n = args.length - 1; n >= 0; n--) { + if (args[n] instanceof RubyModule) { + final RubyModule included = (RubyModule) args[n]; + + // Note that we do appear to do full method lookup here + included.getLookupNode().lookupMethod("append_features").call(null, included, null, main.getSingletonClass()); + + // TODO(cs): call included hook + } + } + + return NilPlaceholder.INSTANCE; + } + } + + @CoreMethod(names = "to_s", needsSelf = false, maxArgs = 0) + public abstract static class ToSNode extends CoreMethodNode { + + public ToSNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToSNode(ToSNode prev) { + super(prev); + } + + @Specialization + public RubyString toS() { + return getContext().makeString("main"); + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/MatchDataNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/MatchDataNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +@CoreClass(name = "MatchData") +public abstract class MatchDataNodes { + + @CoreMethod(names = "[]", minArgs = 1, maxArgs = 1) + public abstract static class GetIndexNode extends CoreMethodNode { + + public GetIndexNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public GetIndexNode(GetIndexNode prev) { + super(prev); + } + + @Specialization + public Object getIndex(RubyMatchData matchData, int index) { + return matchData.getValues()[index]; + } + + } + + @CoreMethod(names = "to_a", maxArgs = 0) + public abstract static class ToANode extends CoreMethodNode { + + public ToANode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToANode(ToANode prev) { + super(prev); + } + + @Specialization + public RubyArray toA(RubyMatchData matchData) { + return RubyArray.specializedFromObjects(getContext().getCoreLibrary().getArrayClass(), matchData.getValues()); + } + + } + + @CoreMethod(names = "values_at", isSplatted = true) + public abstract static class ValuesAtNode extends CoreMethodNode { + + public ValuesAtNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ValuesAtNode(ValuesAtNode prev) { + super(prev); + } + + @Specialization + public RubyArray valuesAt(RubyMatchData matchData, Object[] args) { + final int[] indicies = new int[args.length]; + + for (int n = 0; n < args.length; n++) { + indicies[n] = (int) args[n]; + } + + return RubyArray.specializedFromObjects(getContext().getCoreLibrary().getArrayClass(), matchData.valuesAt(indicies)); + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/MathNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/MathNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import java.math.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.ruby.runtime.*; + +@CoreClass(name = "Math") +public abstract class MathNodes { + + @CoreMethod(names = "sqrt", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class SqrtNode extends CoreMethodNode { + + public SqrtNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SqrtNode(SqrtNode prev) { + super(prev); + } + + @Specialization + public double sqrt(int a) { + return Math.sqrt(a); + } + + @Specialization + public double sqrt(BigInteger a) { + return Math.sqrt(a.doubleValue()); + } + + @Specialization + public double sqrt(double a) { + return Math.sqrt(a); + } + + } + + @CoreMethod(names = "exp", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class ExpNode extends CoreMethodNode { + + public ExpNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ExpNode(ExpNode prev) { + super(prev); + } + + @Specialization + public double exp(int a) { + return Math.exp(a); + } + + @Specialization + public double exp(BigInteger a) { + return Math.exp(a.doubleValue()); + } + + @Specialization + public double exp(double a) { + return Math.exp(a); + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ModuleNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ModuleNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,652 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.nodes.control.*; +import com.oracle.truffle.ruby.nodes.methods.arguments.*; +import com.oracle.truffle.ruby.nodes.objects.*; +import com.oracle.truffle.ruby.nodes.objects.instancevariables.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.RubyParser.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +@CoreClass(name = "Module") +public abstract class ModuleNodes { + + @CoreMethod(names = "alias_method", minArgs = 2, maxArgs = 2) + public abstract static class AliasMethodNode extends CoreMethodNode { + + public AliasMethodNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public AliasMethodNode(AliasMethodNode prev) { + super(prev); + } + + @Specialization + public RubyModule aliasMethod(RubyModule module, RubySymbol newName, RubySymbol oldName) { + module.alias(newName.toString(), oldName.toString()); + return module; + } + } + + @CoreMethod(names = "append_features", minArgs = 1, maxArgs = 1) + public abstract static class AppendFeaturesNode extends CoreMethodNode { + + public AppendFeaturesNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public AppendFeaturesNode(AppendFeaturesNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder appendFeatures(RubyModule module, RubyModule other) { + module.appendFeatures(other); + return NilPlaceholder.INSTANCE; + } + } + + @CoreMethod(names = "attr_reader", isSplatted = true, appendCallNode = true) + public abstract static class AttrReaderNode extends CoreMethodNode { + + public AttrReaderNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public AttrReaderNode(AttrReaderNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder attrReader(RubyModule module, Object[] args) { + final Node callSite = (Node) args[args.length - 1]; + final SourceSection sourceSection = callSite.getSourceSection(); + + for (int n = 0; n < args.length - 1; n++) { + attrReader(getContext(), sourceSection, module, args[n].toString()); + } + + return NilPlaceholder.INSTANCE; + } + + public static void attrReader(RubyContext context, SourceSection sourceSection, RubyModule module, String name) { + CompilerDirectives.transferToInterpreter(); + + final CheckArityNode checkArity = new CheckArityNode(context, sourceSection, Arity.NO_ARGS); + + final SelfNode self = new SelfNode(context, sourceSection); + final UninitializedReadInstanceVariableNode readInstanceVariable = new UninitializedReadInstanceVariableNode(context, sourceSection, name, self); + + final SequenceNode block = new SequenceNode(context, sourceSection, checkArity, readInstanceVariable); + + final RubyRootNode pristineRoot = new RubyRootNode(sourceSection, name + "(attr_reader)", block); + final CallTarget callTarget = Truffle.getRuntime().createCallTarget(NodeUtil.cloneNode(pristineRoot)); + final InlinableMethodImplementation methodImplementation = new InlinableMethodImplementation(callTarget, null, new FrameDescriptor(), pristineRoot, true, false); + final RubyMethod method = new RubyMethod(sourceSection, module, new UniqueMethodIdentifier(), null, name, Visibility.PUBLIC, false, methodImplementation); + + module.addMethod(method); + } + } + + @CoreMethod(names = "attr_writer", isSplatted = true, appendCallNode = true) + public abstract static class AttrWriterNode extends CoreMethodNode { + + public AttrWriterNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public AttrWriterNode(AttrWriterNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder attrWriter(RubyModule module, Object[] args) { + final Node callSite = (Node) args[args.length - 1]; + final SourceSection sourceSection = callSite.getSourceSection(); + + for (int n = 0; n < args.length - 1; n++) { + attrWriter(getContext(), sourceSection, module, args[n].toString()); + } + + return NilPlaceholder.INSTANCE; + } + + public static void attrWriter(RubyContext context, SourceSection sourceSection, RubyModule module, String name) { + CompilerDirectives.transferToInterpreter(); + + final CheckArityNode checkArity = new CheckArityNode(context, sourceSection, Arity.ONE_ARG); + + final SelfNode self = new SelfNode(context, sourceSection); + final ReadPreArgumentNode readArgument = new ReadPreArgumentNode(context, sourceSection, 0, false); + final UninitializedWriteInstanceVariableNode writeInstanceVariable = new UninitializedWriteInstanceVariableNode(context, sourceSection, name, self, readArgument); + + final SequenceNode block = new SequenceNode(context, sourceSection, checkArity, writeInstanceVariable); + + final RubyRootNode pristineRoot = new RubyRootNode(sourceSection, name + "(attr_writer)", block); + final CallTarget callTarget = Truffle.getRuntime().createCallTarget(NodeUtil.cloneNode(pristineRoot)); + final InlinableMethodImplementation methodImplementation = new InlinableMethodImplementation(callTarget, null, new FrameDescriptor(), pristineRoot, true, false); + final RubyMethod method = new RubyMethod(sourceSection, module, new UniqueMethodIdentifier(), null, name + "=", Visibility.PUBLIC, false, methodImplementation); + + module.addMethod(method); + } + } + + @CoreMethod(names = {"attr_accessor", "attr"}, isSplatted = true, appendCallNode = true) + public abstract static class AttrAccessorNode extends CoreMethodNode { + + public AttrAccessorNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public AttrAccessorNode(AttrAccessorNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder attrAccessor(RubyModule module, Object[] args) { + final Node callSite = (Node) args[args.length - 1]; + final SourceSection sourceSection = callSite.getSourceSection(); + + for (int n = 0; n < args.length - 1; n++) { + attrAccessor(getContext(), sourceSection, module, args[n].toString()); + } + + return NilPlaceholder.INSTANCE; + } + + public static void attrAccessor(RubyContext context, SourceSection sourceSection, RubyModule module, String name) { + CompilerDirectives.transferToInterpreter(); + AttrReaderNode.attrReader(context, sourceSection, module, name); + AttrWriterNode.attrWriter(context, sourceSection, module, name); + } + + } + + @CoreMethod(names = "class_eval", minArgs = 1, maxArgs = 3) + public abstract static class ClassEvalNode extends CoreMethodNode { + + public ClassEvalNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ClassEvalNode(ClassEvalNode prev) { + super(prev); + } + + @Specialization + public Object classEval(VirtualFrame frame, RubyModule module, RubyString code, @SuppressWarnings("unused") UndefinedPlaceholder file, @SuppressWarnings("unused") UndefinedPlaceholder line) { + final Source source = getContext().getSourceManager().get("(eval)", code.toString()); + return getContext().execute(getContext(), source, ParserContext.MODULE, module, frame.materialize()); + } + + @Specialization + public Object classEval(VirtualFrame frame, RubyModule module, RubyString code, RubyString file, @SuppressWarnings("unused") UndefinedPlaceholder line) { + final Source source = getContext().getSourceManager().get(file.toString(), code.toString()); + return getContext().execute(getContext(), source, ParserContext.MODULE, module, frame.materialize()); + } + + @Specialization + public Object classEval(VirtualFrame frame, RubyModule module, RubyString code, RubyString file, @SuppressWarnings("unused") int line) { + final Source source = getContext().getSourceManager().get(file.toString(), code.toString()); + return getContext().execute(getContext(), source, ParserContext.MODULE, module, frame.materialize()); + } + + } + + @CoreMethod(names = "class_variable_defined?", maxArgs = 0) + public abstract static class ClassVariableDefinedNode extends CoreMethodNode { + + public ClassVariableDefinedNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ClassVariableDefinedNode(ClassVariableDefinedNode prev) { + super(prev); + } + + @Specialization + public boolean isClassVariableDefined(RubyModule module, RubyString name) { + return module.lookupClassVariable(name.toString()) != null; + } + + @Specialization + public boolean isClassVariableDefined(RubyModule module, RubySymbol name) { + return module.lookupClassVariable(name.toString()) != null; + } + + } + + @CoreMethod(names = "constants", maxArgs = 0) + public abstract static class ConstantsNode extends CoreMethodNode { + + public ConstantsNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ConstantsNode(ConstantsNode prev) { + super(prev); + } + + @Specialization + public RubyArray constants(@SuppressWarnings("unused") RubyModule module) { + getContext().implementationMessage("Module#constants returns an empty array"); + return new RubyArray(getContext().getCoreLibrary().getArrayClass()); + } + } + + @CoreMethod(names = "const_defined?", minArgs = 1, maxArgs = 2) + public abstract static class ConstDefinedNode extends CoreMethodNode { + + public ConstDefinedNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ConstDefinedNode(ConstDefinedNode prev) { + super(prev); + } + + @Specialization(order = 1) + public boolean isConstDefined(RubyModule module, RubyString name, @SuppressWarnings("unused") UndefinedPlaceholder inherit) { + return module.lookupConstant(name.toString()) != null; + } + + @Specialization(order = 2) + public boolean isConstDefined(RubyModule module, RubyString name, boolean inherit) { + if (inherit) { + return module.lookupConstant(name.toString()) != null; + } else { + return module.getConstants().containsKey(name.toString()); + } + } + + @Specialization(order = 3) + public boolean isConstDefined(RubyModule module, RubySymbol name, @SuppressWarnings("unused") UndefinedPlaceholder inherit) { + return module.lookupConstant(name.toString()) != null; + } + + public boolean isConstDefined(RubyModule module, RubySymbol name, boolean inherit) { + if (inherit) { + return module.lookupConstant(name.toString()) != null; + } else { + return module.getConstants().containsKey(name.toString()); + } + } + + } + + @CoreMethod(names = "define_method", needsBlock = true, minArgs = 1, maxArgs = 2) + public abstract static class DefineMethodNode extends CoreMethodNode { + + public DefineMethodNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public DefineMethodNode(DefineMethodNode prev) { + super(prev); + } + + @Specialization(order = 1) + public RubyMethod defineMethod(RubyModule module, RubyString name, @SuppressWarnings("unused") UndefinedPlaceholder proc, RubyProc block) { + final RubyMethod method = block.getMethod(); + module.addMethod(method.withNewName(name.toString())); + return method; + } + + @Specialization(order = 2) + public RubyMethod defineMethod(RubyModule module, RubyString name, RubyProc proc, @SuppressWarnings("unused") UndefinedPlaceholder block) { + final RubyMethod method = proc.getMethod(); + module.addMethod(method.withNewName(name.toString())); + return method; + } + + @Specialization(order = 3) + public RubyMethod defineMethod(RubyModule module, RubySymbol name, @SuppressWarnings("unused") UndefinedPlaceholder proc, RubyProc block) { + final RubyMethod method = block.getMethod(); + module.addMethod(method.withNewName(name.toString())); + return method; + } + + @Specialization(order = 4) + public RubyMethod defineMethod(RubyModule module, RubySymbol name, RubyProc proc, @SuppressWarnings("unused") UndefinedPlaceholder block) { + final RubyMethod method = proc.getMethod(); + module.addMethod(method.withNewName(name.toString())); + return method; + } + + } + + @CoreMethod(names = "include", isSplatted = true, minArgs = 1) + public abstract static class IncludeNode extends CoreMethodNode { + + public IncludeNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public IncludeNode(IncludeNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder include(RubyModule module, Object[] args) { + // Note that we traverse the arguments backwards + + for (int n = args.length - 1; n >= 0; n--) { + if (args[n] instanceof RubyModule) { + final RubyModule included = (RubyModule) args[n]; + + // Note that we do appear to do full method lookup here + included.getLookupNode().lookupMethod("append_features").call(null, included, null, module); + + // TODO(cs): call included hook + } + } + + return NilPlaceholder.INSTANCE; + } + } + + @CoreMethod(names = "method_defined?", minArgs = 1, maxArgs = 2) + public abstract static class MethodDefinedNode extends CoreMethodNode { + + public MethodDefinedNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public MethodDefinedNode(MethodDefinedNode prev) { + super(prev); + } + + @Specialization(order = 1) + public boolean isMethodDefined(RubyModule module, RubyString name, @SuppressWarnings("unused") UndefinedPlaceholder inherit) { + return module.lookupMethod(name.toString()) != null; + } + + @Specialization(order = 2) + public boolean isMethodDefined(RubyModule module, RubyString name, boolean inherit) { + if (inherit) { + return module.lookupMethod(name.toString()) != null; + } else { + return module.getMethods().containsKey(name.toString()); + } + } + + @Specialization(order = 3) + public boolean isMethodDefined(RubyModule module, RubySymbol name, @SuppressWarnings("unused") UndefinedPlaceholder inherit) { + return module.lookupMethod(name.toString()) != null; + } + + public boolean isMethodDefined(RubyModule module, RubySymbol name, boolean inherit) { + if (inherit) { + return module.lookupMethod(name.toString()) != null; + } else { + return module.getMethods().containsKey(name.toString()); + } + } + } + + @CoreMethod(names = "module_eval", minArgs = 1, maxArgs = 3) + public abstract static class ModuleEvalNode extends CoreMethodNode { + + public ModuleEvalNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ModuleEvalNode(ModuleEvalNode prev) { + super(prev); + } + + @Specialization + public RubyModule moduleEval(RubyModule module, RubyString code, @SuppressWarnings("unused") Object file, @SuppressWarnings("unused") Object line) { + module.moduleEval(code.toString()); + return module; + } + } + + @CoreMethod(names = "module_function", isSplatted = true) + public abstract static class ModuleFunctionNode extends CoreMethodNode { + + public ModuleFunctionNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ModuleFunctionNode(ModuleFunctionNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder moduleFunction(VirtualFrame frame, RubyModule module, Object... args) { + if (args.length == 0) { + final Frame unpacked = frame.getCaller().unpack(); + + final FrameSlot slot = unpacked.getFrameDescriptor().findFrameSlot(RubyModule.MODULE_FUNCTION_FLAG_FRAME_SLOT_ID); + + /* + * setObject, even though it's a boolean, so we can getObject and either get the + * default Nil or the boolean value without triggering deoptimization. + */ + + unpacked.setObject(slot, true); + } else { + for (Object argument : args) { + final String methodName = argument.toString(); + module.getSingletonClass().addMethod(module.lookupMethod(methodName)); + } + } + + return NilPlaceholder.INSTANCE; + } + } + + @CoreMethod(names = "public", isSplatted = true) + public abstract static class PublicNode extends CoreMethodNode { + + public PublicNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public PublicNode(PublicNode prev) { + super(prev); + } + + @Specialization + public RubyModule doPublic(VirtualFrame frame, RubyModule module, Object... args) { + module.visibilityMethod(frame.getCaller(), args, Visibility.PUBLIC); + return module; + } + } + + @CoreMethod(names = "private", isSplatted = true) + public abstract static class PrivateNode extends CoreMethodNode { + + public PrivateNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public PrivateNode(PrivateNode prev) { + super(prev); + } + + @Specialization + public RubyModule doPrivate(VirtualFrame frame, RubyModule module, Object... args) { + module.visibilityMethod(frame.getCaller(), args, Visibility.PRIVATE); + return module; + } + } + + @CoreMethod(names = "private_class_method", isSplatted = true) + public abstract static class PrivateClassMethodNode extends CoreMethodNode { + + public PrivateClassMethodNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public PrivateClassMethodNode(PrivateClassMethodNode prev) { + super(prev); + } + + @Specialization + public RubyModule privateClassMethod(RubyModule module, Object... args) { + final RubyClass moduleSingleton = module.getSingletonClass(); + + for (Object arg : args) { + final RubyMethod method = moduleSingleton.lookupMethod(arg.toString()); + + if (method == null) { + throw new RuntimeException("Couldn't find method " + arg.toString()); + } + + moduleSingleton.addMethod(method.withNewVisibility(Visibility.PRIVATE)); + } + + return module; + } + } + + @CoreMethod(names = "private_constant", isSplatted = true) + public abstract static class PrivateConstantNode extends CoreMethodNode { + + public PrivateConstantNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public PrivateConstantNode(PrivateConstantNode prev) { + super(prev); + } + + @Specialization + public RubyModule privateConstnat(RubyModule module, @SuppressWarnings("unused") Object... args) { + getContext().implementationMessage("private_constant does nothing at the moment"); + return module; + } + } + + @CoreMethod(names = "protected", isSplatted = true) + public abstract static class ProtectedNode extends CoreMethodNode { + + public ProtectedNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ProtectedNode(ProtectedNode prev) { + super(prev); + } + + @Specialization + public RubyModule doProtected(RubyModule module, @SuppressWarnings("unused") Object... args) { + getContext().implementationMessage("protected does nothing at the moment"); + return module; + } + } + + @CoreMethod(names = "remove_class_variable", minArgs = 1, maxArgs = 1) + public abstract static class RemoveClassVariableNode extends CoreMethodNode { + + public RemoveClassVariableNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public RemoveClassVariableNode(RemoveClassVariableNode prev) { + super(prev); + } + + @Specialization + public RubyModule removeClassVariable(RubyModule module, RubyString name) { + module.removeClassVariable(name.toString()); + return module; + } + + @Specialization + public RubyModule removeClassVariable(RubyModule module, RubySymbol name) { + module.removeClassVariable(name.toString()); + return module; + } + + } + + @CoreMethod(names = "remove_method", minArgs = 1, maxArgs = 1) + public abstract static class RemoveMethodNode extends CoreMethodNode { + + public RemoveMethodNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public RemoveMethodNode(RemoveMethodNode prev) { + super(prev); + } + + @Specialization + public RubyModule removeMethod(RubyModule module, RubyString name) { + module.removeMethod(name.toString()); + return module; + } + + @Specialization + public RubyModule removeMethod(RubyModule module, RubySymbol name) { + module.removeMethod(name.toString()); + return module; + } + + } + + @CoreMethod(names = "to_s", maxArgs = 0) + public abstract static class ToSNode extends CoreMethodNode { + + public ToSNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToSNode(ToSNode prev) { + super(prev); + } + + @Specialization + public RubyString toS(RubyModule module) { + return getContext().makeString(module.getName()); + } + } + + @CoreMethod(names = "undef_method", minArgs = 1, maxArgs = 1) + public abstract static class UndefMethodNode extends CoreMethodNode { + + public UndefMethodNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public UndefMethodNode(UndefMethodNode prev) { + super(prev); + } + + @Specialization + public RubyModule undefMethod(RubyModule module, RubyString name) { + final RubyMethod method = module.lookupMethod(name.toString()); + module.undefMethod(method); + return module; + } + + @Specialization + public RubyModule undefMethod(RubyModule module, RubySymbol name) { + final RubyMethod method = module.lookupMethod(name.toString()); + module.undefMethod(method); + return module; + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/NilClassNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/NilClassNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +@CoreClass(name = "NilClass") +public abstract class NilClassNodes { + + @CoreMethod(names = "!", needsSelf = false, maxArgs = 0) + public abstract static class NotNode extends CoreMethodNode { + + public NotNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public NotNode(NotNode prev) { + super(prev); + } + + @Specialization + public boolean not() { + return true; + } + } + + @CoreMethod(names = "==", needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class EqualNode extends CoreMethodNode { + + public EqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EqualNode(EqualNode prev) { + super(prev); + } + + @Specialization + public boolean equal(Object b) { + return b instanceof NilPlaceholder || b instanceof RubyNilClass; + } + + } + + @CoreMethod(names = "!=", needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class NotEqualNode extends CoreMethodNode { + + public NotEqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public NotEqualNode(NotEqualNode prev) { + super(prev); + } + + @Specialization + public boolean equal(Object b) { + return !(b instanceof NilPlaceholder || b instanceof RubyNilClass); + } + + } + + @CoreMethod(names = "inspect", needsSelf = false, maxArgs = 0) + public abstract static class InpsectNode extends CoreMethodNode { + + public InpsectNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InpsectNode(InpsectNode prev) { + super(prev); + } + + @Specialization + public RubyString inspect() { + return getContext().makeString("nil"); + } + } + + @CoreMethod(names = "nil?", needsSelf = false, maxArgs = 0) + public abstract static class NilNode extends CoreMethodNode { + + public NilNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public NilNode(NilNode prev) { + super(prev); + } + + @Specialization + public boolean nil() { + return true; + } + } + + @CoreMethod(names = "to_i", needsSelf = false, maxArgs = 0) + public abstract static class ToINode extends CoreMethodNode { + + public ToINode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToINode(ToINode prev) { + super(prev); + } + + @Specialization + public int toI() { + return 0; + } + } + + @CoreMethod(names = "to_s", needsSelf = false, maxArgs = 0) + public abstract static class ToSNode extends CoreMethodNode { + + public ToSNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToSNode(ToSNode prev) { + super(prev); + } + + @Specialization + public RubyString toS() { + return getContext().makeString(""); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ObjectNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ObjectNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,514 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import java.math.*; +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; +import com.oracle.truffle.ruby.runtime.methods.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +@CoreClass(name = "Object") +public abstract class ObjectNodes { + + @CoreMethod(names = "class", maxArgs = 0) + public abstract static class ClassNode extends CoreMethodNode { + + public ClassNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ClassNode(ClassNode prev) { + super(prev); + } + + @Specialization + public RubyClass getClass(boolean value) { + if (value) { + return getContext().getCoreLibrary().getTrueClass(); + } else { + return getContext().getCoreLibrary().getFalseClass(); + } + } + + @Specialization + public RubyClass getClass(@SuppressWarnings("unused") int value) { + return getContext().getCoreLibrary().getFixnumClass(); + } + + @Specialization + public RubyClass getClass(@SuppressWarnings("unused") BigInteger value) { + return getContext().getCoreLibrary().getBignumClass(); + } + + @Specialization + public RubyClass getClass(@SuppressWarnings("unused") double value) { + return getContext().getCoreLibrary().getFloatClass(); + } + + @Specialization + public RubyClass getClass(RubyBasicObject self) { + return self.getRubyClass(); + } + + } + + @CoreMethod(names = "dup", maxArgs = 0) + public abstract static class DupNode extends CoreMethodNode { + + public DupNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public DupNode(DupNode prev) { + super(prev); + } + + @Specialization + public Object dup(RubyObject self) { + return self.dup(); + } + + } + + @CoreMethod(names = "extend", isSplatted = true, minArgs = 1) + public abstract static class ExtendNode extends CoreMethodNode { + + public ExtendNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ExtendNode(ExtendNode prev) { + super(prev); + } + + @Specialization + public RubyBasicObject extend(RubyBasicObject self, Object[] args) { + for (int n = 0; n < args.length; n++) { + self.extend((RubyModule) args[n]); + } + + return self; + } + + } + + @CoreMethod(names = "freeze", maxArgs = 0) + public abstract static class FreezeNode extends CoreMethodNode { + + public FreezeNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public FreezeNode(FreezeNode prev) { + super(prev); + } + + @Specialization + public RubyObject freeze(RubyObject self) { + self.frozen = true; + return self; + } + + } + + @CoreMethod(names = "frozen?", maxArgs = 0) + public abstract static class FrozenNode extends CoreMethodNode { + + public FrozenNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public FrozenNode(FrozenNode prev) { + super(prev); + } + + @Specialization + public boolean isFrozen(RubyObject self) { + return self.frozen; + } + + } + + @CoreMethod(names = "inspect", maxArgs = 0) + public abstract static class InspectNode extends CoreMethodNode { + + public InspectNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InspectNode(InspectNode prev) { + super(prev); + } + + @Specialization + public RubyString inspect(boolean value) { + return getContext().makeString(Boolean.toString(value)); + } + + @Specialization + public RubyString inspect(int value) { + return getContext().makeString(Integer.toString(value)); + } + + @Specialization + public RubyString inspect(BigInteger value) { + return getContext().makeString(value.toString()); + } + + @Specialization + public RubyString inspect(double value) { + return getContext().makeString(Double.toString(value)); + } + + @Specialization + public RubyString inspect(RubyObject self) { + return getContext().makeString(self.inspect()); + } + + } + + @CoreMethod(names = "instance_eval", needsBlock = true, maxArgs = 0) + public abstract static class InstanceEvalNode extends CoreMethodNode { + + public InstanceEvalNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InstanceEvalNode(InstanceEvalNode prev) { + super(prev); + } + + @Specialization + public Object instanceEval(VirtualFrame frame, RubyObject self, RubyProc block) { + return block.callWithModifiedSelf(frame.pack(), self); + } + + } + + @CoreMethod(names = "instance_variable_defined?", minArgs = 1, maxArgs = 1) + public abstract static class InstanceVariableDefinedNode extends CoreMethodNode { + + public InstanceVariableDefinedNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InstanceVariableDefinedNode(InstanceVariableDefinedNode prev) { + super(prev); + } + + @Specialization + public boolean isInstanceVariableDefined(RubyBasicObject object, RubyString name) { + return object.isInstanceVariableDefined(RubyObject.checkInstanceVariableName(getContext(), name.toString())); + } + + @Specialization + public boolean isInstanceVariableDefined(RubyBasicObject object, RubySymbol name) { + return object.isInstanceVariableDefined(RubyObject.checkInstanceVariableName(getContext(), name.toString())); + } + + } + + @CoreMethod(names = "instance_variable_get", minArgs = 1, maxArgs = 1) + public abstract static class InstanceVariableGetNode extends CoreMethodNode { + + public InstanceVariableGetNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InstanceVariableGetNode(InstanceVariableGetNode prev) { + super(prev); + } + + @Specialization + public Object isInstanceVariableGet(RubyBasicObject object, RubyString name) { + return object.getInstanceVariable(RubyObject.checkInstanceVariableName(getContext(), name.toString())); + } + + @Specialization + public Object isInstanceVariableGet(RubyBasicObject object, RubySymbol name) { + return object.getInstanceVariable(RubyObject.checkInstanceVariableName(getContext(), name.toString())); + } + + } + + @CoreMethod(names = "instance_variable_set", minArgs = 2, maxArgs = 2) + public abstract static class InstanceVariableSetNode extends CoreMethodNode { + + public InstanceVariableSetNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InstanceVariableSetNode(InstanceVariableSetNode prev) { + super(prev); + } + + @Specialization + public Object isInstanceVariableSet(RubyBasicObject object, RubyString name, Object value) { + object.setInstanceVariable(RubyObject.checkInstanceVariableName(getContext(), name.toString()), value); + return value; + } + + @Specialization + public Object isInstanceVariableSet(RubyBasicObject object, RubySymbol name, Object value) { + object.setInstanceVariable(RubyObject.checkInstanceVariableName(getContext(), name.toString()), value); + return value; + } + + } + + @CoreMethod(names = "instance_variables", maxArgs = 0) + public abstract static class InstanceVariablesNode extends CoreMethodNode { + + public InstanceVariablesNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InstanceVariablesNode(InstanceVariablesNode prev) { + super(prev); + } + + @Specialization + public RubyArray instanceVariables(RubyObject self) { + final String[] instanceVariableNames = self.getInstanceVariableNames(); + + Arrays.sort(instanceVariableNames); + + final RubyArray array = new RubyArray(getContext().getCoreLibrary().getArrayClass()); + + for (String name : instanceVariableNames) { + array.push(new RubyString(getContext().getCoreLibrary().getStringClass(), name)); + } + + return array; + } + + } + + @CoreMethod(names = {"is_a?", "instance_of?", "kind_of?"}, minArgs = 1, maxArgs = 1) + public abstract static class IsANode extends CoreMethodNode { + + public IsANode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public IsANode(IsANode prev) { + super(prev); + } + + @Specialization + public boolean isA(@SuppressWarnings("unused") RubyObject self, @SuppressWarnings("unused") NilPlaceholder nil) { + return false; + } + + @Specialization + public boolean isA(RubyObject self, RubyClass rubyClass) { + return self.getRubyClass().assignableTo(rubyClass); + } + + } + + @CoreMethod(names = "methods", minArgs = 0, maxArgs = 1) + public abstract static class MethodsNode extends CoreMethodNode { + + public MethodsNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public MethodsNode(MethodsNode prev) { + super(prev); + } + + @Specialization + public RubyArray methods(RubyObject self, boolean includeInherited) { + if (!includeInherited) { + self.getRubyClass().getContext().implementationMessage("Object#methods always returns inherited methods at the moment"); + } + + return methods(self, UndefinedPlaceholder.INSTANCE); + } + + @Specialization + public RubyArray methods(RubyObject self, @SuppressWarnings("unused") UndefinedPlaceholder includeInherited) { + final RubyArray array = new RubyArray(self.getRubyClass().getContext().getCoreLibrary().getArrayClass()); + + final Map methods = new HashMap<>(); + + self.getLookupNode().getMethods(methods); + + for (RubyMethod method : methods.values()) { + if (method.getVisibility() == Visibility.PUBLIC || method.getVisibility() == Visibility.PROTECTED) { + array.push(new RubySymbol(self.getRubyClass().getContext().getCoreLibrary().getSymbolClass(), method.getName())); + } + } + + return array; + } + + } + + @CoreMethod(names = "nil?", needsSelf = false, maxArgs = 0) + public abstract static class NilNode extends CoreMethodNode { + + public NilNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public NilNode(NilNode prev) { + super(prev); + } + + @Specialization + public boolean nil() { + return false; + } + } + + @CoreMethod(names = "object_id", needsSelf = true, maxArgs = 0) + public abstract static class ObjectIDNode extends CoreMethodNode { + + public ObjectIDNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ObjectIDNode(ObjectIDNode prev) { + super(prev); + } + + @Specialization + public Object objectID(RubyBasicObject object) { + return GeneralConversions.fixnumOrBignum(object.getObjectID()); + } + + } + + @CoreMethod(names = "respond_to?", minArgs = 1, maxArgs = 2) + public abstract static class RespondToNode extends CoreMethodNode { + + public RespondToNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public RespondToNode(RespondToNode prev) { + super(prev); + } + + @Specialization(order = 1) + public boolean doesRespondTo(Object object, RubyString name, @SuppressWarnings("unused") UndefinedPlaceholder checkVisibility) { + return doesRespondTo(getContext().getCoreLibrary().box(object), name.toString(), false); + } + + @Specialization(order = 2) + public boolean doesRespondTo(Object object, RubyString name, boolean dontCheckVisibility) { + return doesRespondTo(getContext().getCoreLibrary().box(object), name.toString(), dontCheckVisibility); + } + + @Specialization(order = 3) + public boolean doesRespondTo(Object object, RubySymbol name, @SuppressWarnings("unused") UndefinedPlaceholder checkVisibility) { + return doesRespondTo(getContext().getCoreLibrary().box(object), name.toString(), false); + } + + @Specialization(order = 4) + public boolean doesRespondTo(Object object, RubySymbol name, boolean dontCheckVisibility) { + return doesRespondTo(getContext().getCoreLibrary().box(object), name.toString(), dontCheckVisibility); + } + + private static boolean doesRespondTo(RubyBasicObject object, String name, boolean dontCheckVisibility) { + final RubyMethod method = object.getLookupNode().lookupMethod(name); + + if (method == null || method.isUndefined()) { + return false; + } + + if (dontCheckVisibility) { + return true; + } else { + return method.getVisibility() == Visibility.PUBLIC; + } + } + + } + + @CoreMethod(names = "singleton_class", maxArgs = 0) + public abstract static class SingletonClassNode extends CoreMethodNode { + + public SingletonClassNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SingletonClassNode(SingletonClassNode prev) { + super(prev); + } + + @Specialization + public RubyClass singletonClass(RubyBasicObject self) { + return self.getSingletonClass(); + } + + } + + @CoreMethod(names = "singleton_methods", minArgs = 0, maxArgs = 1) + public abstract static class SingletonMethodsNode extends CoreMethodNode { + + public SingletonMethodsNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SingletonMethodsNode(SingletonMethodsNode prev) { + super(prev); + } + + @Specialization + public RubyArray singletonMethods(RubyObject self, boolean includeInherited) { + if (!includeInherited) { + self.getRubyClass().getContext().implementationMessage("Object#singleton_methods always returns inherited methods at the moment"); + } + + return singletonMethods(self, UndefinedPlaceholder.INSTANCE); + } + + @Specialization + public RubyArray singletonMethods(RubyObject self, @SuppressWarnings("unused") UndefinedPlaceholder includeInherited) { + final RubyArray array = new RubyArray(self.getRubyClass().getContext().getCoreLibrary().getArrayClass()); + + for (RubyMethod method : self.getSingletonClass().getDeclaredMethods()) { + array.push(new RubySymbol(self.getRubyClass().getContext().getCoreLibrary().getSymbolClass(), method.getName())); + } + + return array; + } + + } + + @CoreMethod(names = "to_s", maxArgs = 0) + public abstract static class ToSNode extends CoreMethodNode { + + public ToSNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToSNode(ToSNode prev) { + super(prev); + } + + @Specialization + public RubyString toS(RubyObject self) { + return getContext().makeString(self.toString()); + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ObjectSpaceNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ObjectSpaceNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import java.math.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +@CoreClass(name = "ObjectSpace") +public abstract class ObjectSpaceNodes { + + @CoreMethod(names = "_id2ref", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class ID2RefNode extends CoreMethodNode { + + public ID2RefNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ID2RefNode(ID2RefNode prev) { + super(prev); + } + + @Specialization + public Object id2Ref(int id) { + final Object object = getContext().getObjectSpaceManager().lookupId(id); + + if (object == null) { + return NilPlaceholder.INSTANCE; + } else { + return object; + } + } + + @Specialization + public Object id2Ref(BigInteger id) { + final Object object = getContext().getObjectSpaceManager().lookupId(id.longValue()); + + if (object == null) { + return NilPlaceholder.INSTANCE; + } else { + return object; + } + } + + } + + @CoreMethod(names = "each_object", isModuleMethod = true, needsSelf = false, needsBlock = true, minArgs = 0, maxArgs = 1) + public abstract static class EachObjectNode extends YieldingCoreMethodNode { + + public EachObjectNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EachObjectNode(EachObjectNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder eachObject(VirtualFrame frame, @SuppressWarnings("unused") UndefinedPlaceholder ofClass, RubyProc block) { + for (RubyBasicObject object : getContext().getObjectSpaceManager().getObjects()) { + yield(frame, block, object); + } + return NilPlaceholder.INSTANCE; + } + + @Specialization + public NilPlaceholder eachObject(VirtualFrame frame, RubyClass ofClass, RubyProc block) { + for (RubyBasicObject object : getContext().getObjectSpaceManager().getObjects()) { + if (object.getRubyClass().assignableTo(ofClass)) { + yield(frame, block, object); + } + } + return NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = "define_finalizer", isModuleMethod = true, needsSelf = false, minArgs = 2, maxArgs = 2) + public abstract static class DefineFinalizerNode extends CoreMethodNode { + + public DefineFinalizerNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public DefineFinalizerNode(DefineFinalizerNode prev) { + super(prev); + } + + @Specialization + public RubyProc defineFinalizer(Object object, RubyProc finalizer) { + getContext().getObjectSpaceManager().defineFinalizer((RubyBasicObject) object, finalizer); + return finalizer; + } + } + + @CoreMethod(names = {"garbage_collect", "start"}, isModuleMethod = true, needsSelf = false, maxArgs = 0) + public abstract static class GarbageCollectNode extends CoreMethodNode { + + public GarbageCollectNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public GarbageCollectNode(GarbageCollectNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder garbageCollect() { + final RubyThread runningThread = getContext().getThreadManager().leaveGlobalLock(); + + try { + System.gc(); + } finally { + getContext().getThreadManager().enterGlobalLock(runningThread); + } + + return NilPlaceholder.INSTANCE; + } + } + + @CoreMethod(names = "undefine_finalizer", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class UndefineFinalizerNode extends CoreMethodNode { + + public UndefineFinalizerNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public UndefineFinalizerNode(UndefineFinalizerNode prev) { + super(prev); + } + + @Specialization + public Object undefineFinalizer(Object object) { + getContext().getObjectSpaceManager().undefineFinalizer((RubyBasicObject) object); + return object; + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ProcNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ProcNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +@CoreClass(name = "Proc") +public abstract class ProcNodes { + + @CoreMethod(names = {"call", "[]"}, isSplatted = true) + public abstract static class CallNode extends CoreMethodNode { + + public CallNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public CallNode(CallNode prev) { + super(prev); + } + + @Specialization + public Object call(VirtualFrame frame, RubyProc proc, Object[] args) { + return proc.call(frame.getCaller(), args); + } + + } + + @CoreMethod(names = "initialize", needsBlock = true, maxArgs = 0) + public abstract static class InitializeNode extends CoreMethodNode { + + public InitializeNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InitializeNode(InitializeNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder initialize(VirtualFrame frame, RubyProc proc, RubyProc block) { + final RubyArguments callerArguments = frame.getCaller().unpack().getArguments(RubyArguments.class); + proc.initialize(RubyProc.Type.PROC, callerArguments.getSelf(), callerArguments.getBlock(), block.getMethod()); + return NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = "lambda?", maxArgs = 0) + public abstract static class LambdaNode extends CoreMethodNode { + + public LambdaNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public LambdaNode(LambdaNode prev) { + super(prev); + } + + @Specialization + public boolean lambda(RubyProc proc) { + return proc.getType() == RubyProc.Type.LAMBDA; + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ProcessNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ProcessNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.ruby.runtime.*; + +@CoreClass(name = "Process") +public abstract class ProcessNodes { + + @CoreMethod(names = "pid", isModuleMethod = true, needsSelf = false, maxArgs = 0) + public abstract static class PidNode extends CoreMethodNode { + + public PidNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public PidNode(PidNode prev) { + super(prev); + } + + @Specialization + public int pid() { + return getContext().getPOSIX().getpid(); + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/RangeNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/RangeNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.call.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; +import com.oracle.truffle.ruby.runtime.core.range.*; + +@CoreClass(name = "Range") +public abstract class RangeNodes { + + @CoreMethod(names = {"collect", "map"}, needsBlock = true, maxArgs = 0) + public abstract static class CollectNode extends YieldingCoreMethodNode { + + public CollectNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public CollectNode(CollectNode prev) { + super(prev); + } + + @Specialization + public RubyArray collect(VirtualFrame frame, FixnumRange range, RubyProc block) { + final RubyContext context = getContext(); + + final RubyArray array = new RubyArray(context.getCoreLibrary().getArrayClass()); + + for (int n = range.getBegin(); n < range.getExclusiveEnd(); n++) { + array.push(yield(frame, block, n)); + } + + return array; + } + + } + + @CoreMethod(names = "each", needsBlock = true, maxArgs = 0) + public abstract static class EachNode extends YieldingCoreMethodNode { + + public EachNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EachNode(EachNode prev) { + super(prev); + } + + @Specialization + public FixnumRange each(VirtualFrame frame, FixnumRange range, RubyProc block) { + for (int n = range.getBegin(); n < range.getExclusiveEnd(); n++) { + yield(frame, block, n); + } + + return range; + } + + } + + @CoreMethod(names = "exclude_end?", maxArgs = 0) + public abstract static class ExcludeEndNode extends CoreMethodNode { + + public ExcludeEndNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ExcludeEndNode(ExcludeEndNode prev) { + super(prev); + } + + @Specialization + public boolean excludeEnd(RubyRange range) { + return range.doesExcludeEnd(); + } + + } + + @CoreMethod(names = "first", maxArgs = 0) + public abstract static class FirstNode extends CoreMethodNode { + + public FirstNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public FirstNode(FirstNode prev) { + super(prev); + } + + @Specialization + public int each(FixnumRange range) { + return range.getBegin(); + } + + @Specialization + public Object each(ObjectRange range) { + return range.getBegin(); + } + + } + + @CoreMethod(names = "include?", maxArgs = 1) + public abstract static class IncludeNode extends CoreMethodNode { + + @Child protected DispatchHeadNode callLess; + @Child protected DispatchHeadNode callGreater; + @Child protected DispatchHeadNode callGreaterEqual; + + public IncludeNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + callLess = adoptChild(new DispatchHeadNode(context, getSourceSection(), "<", false)); + callGreater = adoptChild(new DispatchHeadNode(context, getSourceSection(), ">", false)); + callGreaterEqual = adoptChild(new DispatchHeadNode(context, getSourceSection(), ">=", false)); + } + + public IncludeNode(IncludeNode prev) { + super(prev); + callLess = adoptChild(prev.callLess); + callGreater = adoptChild(prev.callGreater); + callGreaterEqual = adoptChild(prev.callGreaterEqual); + } + + @Specialization + public boolean include(FixnumRange range, int value) { + return value >= range.getBegin() && value < range.getExclusiveEnd(); + } + + @Specialization + public boolean include(VirtualFrame frame, ObjectRange range, Object value) { + if ((boolean) callLess.dispatch(frame, value, null, range.getBegin())) { + return false; + } + + if (range.doesExcludeEnd()) { + if ((boolean) callGreaterEqual.dispatch(frame, value, null, range.getEnd())) { + return false; + } + } else { + if ((boolean) callGreater.dispatch(frame, value, null, range.getEnd())) { + return false; + } + } + + return true; + } + } + + @CoreMethod(names = "last", maxArgs = 0) + public abstract static class LastNode extends CoreMethodNode { + + public LastNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public LastNode(LastNode prev) { + super(prev); + } + + @Specialization + public int last(FixnumRange range) { + return range.getEnd(); + } + + @Specialization + public Object last(ObjectRange range) { + return range.getEnd(); + } + + } + + @CoreMethod(names = "step", needsBlock = true, minArgs = 1, maxArgs = 1) + public abstract static class StepNode extends YieldingCoreMethodNode { + + public StepNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public StepNode(StepNode prev) { + super(prev); + } + + @Specialization + public FixnumRange step(VirtualFrame frame, FixnumRange range, int step, RubyProc block) { + for (int n = range.getBegin(); n < range.getExclusiveEnd(); n += step) { + yield(frame, block, n); + } + + return range; + } + + } + + @CoreMethod(names = "to_a", maxArgs = 0) + public abstract static class ToANode extends CoreMethodNode { + + public ToANode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToANode(ToANode prev) { + super(prev); + } + + @Specialization + public RubyArray toA(RubyRange range) { + return range.toArray(); + } + + } + + @CoreMethod(names = "to_s", maxArgs = 0) + public abstract static class ToSNode extends CoreMethodNode { + + public ToSNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToSNode(ToSNode prev) { + super(prev); + } + + @Specialization + public RubyString toS(RubyRange range) { + return getContext().makeString(range.toString()); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/RegexpNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/RegexpNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import java.util.regex.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +@CoreClass(name = "Regexp") +public abstract class RegexpNodes { + + @CoreMethod(names = {"=~", "==="}, minArgs = 1, maxArgs = 1) + public abstract static class MatchOperatorNode extends CoreMethodNode { + + public MatchOperatorNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public MatchOperatorNode(MatchOperatorNode prev) { + super(prev); + } + + @Specialization + public Object match(VirtualFrame frame, RubyRegexp regexp, RubyString string) { + return regexp.matchOperator(frame.getCaller().unpack(), string.toString()); + } + + } + + @CoreMethod(names = "!~", minArgs = 1, maxArgs = 1) + public abstract static class NotMatchOperatorNode extends CoreMethodNode { + + public NotMatchOperatorNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public NotMatchOperatorNode(NotMatchOperatorNode prev) { + super(prev); + } + + @Specialization + public Object match(VirtualFrame frame, RubyRegexp regexp, RubyString string) { + return regexp.matchOperator(frame.getCaller().unpack(), string.toString()) == NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = "escape", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class EscapeNode extends CoreMethodNode { + + public EscapeNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EscapeNode(EscapeNode prev) { + super(prev); + } + + @Specialization + public RubyString sqrt(RubyString pattern) { + return getContext().makeString(Pattern.quote(pattern.toString())); + } + + } + + @CoreMethod(names = "initialize", minArgs = 1, maxArgs = 1) + public abstract static class InitializeNode extends CoreMethodNode { + + public InitializeNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InitializeNode(InitializeNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder initialize(RubyRegexp regexp, RubyString string) { + regexp.initialize(string.toString()); + return NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = "match", minArgs = 1, maxArgs = 1) + public abstract static class MatchNode extends CoreMethodNode { + + public MatchNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public MatchNode(MatchNode prev) { + super(prev); + } + + @Specialization + public Object match(RubyRegexp regexp, RubyString string) { + return regexp.match(string.toString()); + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/SignalNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/SignalNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.ruby.runtime.*; + +@CoreClass(name = "Signal") +public abstract class SignalNodes { + + @CoreMethod(names = "trap", isModuleMethod = true, needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class SignalNode extends CoreMethodNode { + + public SignalNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SignalNode(SignalNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder trap(@SuppressWarnings("unused") Object signal) { + getContext().implementationMessage("Signal#trap doesn't do anything"); + return NilPlaceholder.INSTANCE; + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/StringNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/StringNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,559 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import java.util.*; +import java.util.regex.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +@CoreClass(name = "String") +public abstract class StringNodes { + + @CoreMethod(names = "+", minArgs = 1, maxArgs = 1) + public abstract static class AddNode extends CoreMethodNode { + + public AddNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public AddNode(AddNode prev) { + super(prev); + } + + @Specialization + public RubyString add(RubyString a, RubyString b) { + return new RubyString(a.getRubyClass().getContext().getCoreLibrary().getStringClass(), a.toString() + b.toString()); + } + } + + @CoreMethod(names = {"==", "==="}, minArgs = 1, maxArgs = 1) + public abstract static class EqualNode extends CoreMethodNode { + + public EqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EqualNode(EqualNode prev) { + super(prev); + } + + @Specialization + public boolean equal(@SuppressWarnings("unused") RubyString a, @SuppressWarnings("unused") NilPlaceholder b) { + return false; + } + + @Specialization + public boolean equal(RubyString a, RubyString b) { + return a.toString().equals(b.toString()); + } + } + + @CoreMethod(names = "!=", minArgs = 1, maxArgs = 1) + public abstract static class NotEqualNode extends CoreMethodNode { + + public NotEqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public NotEqualNode(NotEqualNode prev) { + super(prev); + } + + @Specialization + public boolean equal(@SuppressWarnings("unused") RubyString a, @SuppressWarnings("unused") NilPlaceholder b) { + return true; + } + + @Specialization + public boolean notEqual(RubyString a, RubyString b) { + return !a.toString().equals(b.toString()); + } + + } + + @CoreMethod(names = "<=>", minArgs = 1, maxArgs = 1) + public abstract static class CompareNode extends CoreMethodNode { + + public CompareNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public CompareNode(CompareNode prev) { + super(prev); + } + + @Specialization + public int compare(RubyString a, RubyString b) { + return a.toString().compareTo(b.toString()); + } + } + + @CoreMethod(names = "<<", minArgs = 1, maxArgs = 1) + public abstract static class ConcatNode extends CoreMethodNode { + + public ConcatNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ConcatNode(ConcatNode prev) { + super(prev); + } + + @Specialization + public RubyString concat(RubyString string, RubyString other) { + string.replace(string.toString() + other.toString()); + return string; + } + } + + @CoreMethod(names = "%", minArgs = 1, maxArgs = 1, isSplatted = true) + public abstract static class FormatNode extends CoreMethodNode { + + public FormatNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public FormatNode(FormatNode prev) { + super(prev); + } + + @Specialization + public RubyString format(RubyString format, Object[] args) { + final RubyContext context = getContext(); + + if (args.length == 1 && args[0] instanceof RubyArray) { + return context.makeString(StringFormatter.format(format.toString(), ((RubyArray) args[0]).asList())); + } else { + return context.makeString(StringFormatter.format(format.toString(), Arrays.asList(args))); + } + } + } + + @CoreMethod(names = "[]", minArgs = 1, maxArgs = 2, isSplatted = true) + public abstract static class GetIndexNode extends CoreMethodNode { + + public GetIndexNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public GetIndexNode(GetIndexNode prev) { + super(prev); + } + + @Specialization + public Object getIndex(RubyString string, Object[] args) { + return RubyString.getIndex(getContext(), string.toString(), args); + } + } + + @CoreMethod(names = "=~", minArgs = 1, maxArgs = 1) + public abstract static class MatchOperatorNode extends CoreMethodNode { + + public MatchOperatorNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public MatchOperatorNode(MatchOperatorNode prev) { + super(prev); + } + + @Specialization + public Object match(VirtualFrame frame, RubyString string, RubyRegexp regexp) { + return regexp.matchOperator(frame, string.toString()); + } + } + + @CoreMethod(names = "chomp", maxArgs = 0) + public abstract static class ChompNode extends CoreMethodNode { + + public ChompNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ChompNode(ChompNode prev) { + super(prev); + } + + @Specialization + public RubyString chomp(RubyString string) { + return string.getRubyClass().getContext().makeString(string.toString().trim()); + } + } + + @CoreMethod(names = "chomp!", maxArgs = 0) + public abstract static class ChompBangNode extends CoreMethodNode { + + public ChompBangNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ChompBangNode(ChompBangNode prev) { + super(prev); + } + + @Specialization + public RubyString chompBang(RubyString string) { + string.replace(string.toString().trim()); + return string; + } + } + + @CoreMethod(names = "downcase", maxArgs = 0) + public abstract static class DowncaseNode extends CoreMethodNode { + + public DowncaseNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public DowncaseNode(DowncaseNode prev) { + super(prev); + } + + @Specialization + public RubyString downcase(RubyString string) { + return string.getRubyClass().getContext().makeString(string.toString().toLowerCase()); + } + } + + @CoreMethod(names = "downcase!", maxArgs = 0) + public abstract static class DowncaseBangNode extends CoreMethodNode { + + public DowncaseBangNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public DowncaseBangNode(DowncaseBangNode prev) { + super(prev); + } + + @Specialization + public RubyString downcase(RubyString string) { + string.replace(string.toString().toLowerCase()); + return string; + } + } + + @CoreMethod(names = "empty?", maxArgs = 0) + public abstract static class EmptyNode extends CoreMethodNode { + + public EmptyNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EmptyNode(EmptyNode prev) { + super(prev); + } + + @Specialization + public boolean empty(RubyString string) { + return string.toString().isEmpty(); + } + } + + @CoreMethod(names = "end_with?", minArgs = 1, maxArgs = 1) + public abstract static class EndWithNode extends CoreMethodNode { + + public EndWithNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EndWithNode(EndWithNode prev) { + super(prev); + } + + @Specialization + public boolean endWith(RubyString string, RubyString b) { + return string.toString().endsWith(b.toString()); + } + } + + @CoreMethod(names = "gsub", minArgs = 2, maxArgs = 2) + public abstract static class GsubNode extends CoreMethodNode { + + public GsubNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public GsubNode(GsubNode prev) { + super(prev); + } + + @Specialization + public RubyString gsub(RubyString string, RubyString regexpString, RubyString replacement) { + final RubyRegexp regexp = new RubyRegexp(getContext().getCoreLibrary().getRegexpClass(), regexpString.toString()); + return gsub(string, regexp, replacement); + } + + @Specialization + public RubyString gsub(RubyString string, RubyRegexp regexp, RubyString replacement) { + return getContext().makeString(regexp.getPattern().matcher(string.toString()).replaceAll(replacement.toString())); + } + } + + @CoreMethod(names = "inspect", maxArgs = 0) + public abstract static class InpsectNode extends CoreMethodNode { + + public InpsectNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InpsectNode(InpsectNode prev) { + super(prev); + } + + @Specialization + public RubyString inspect(RubyString string) { + return getContext().makeString("\"" + string.toString().replace("\\", "\\\\").replace("\"", "\\\"") + "\""); + } + } + + @CoreMethod(names = "ljust", minArgs = 1, maxArgs = 2) + public abstract static class LjustNode extends CoreMethodNode { + + public LjustNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public LjustNode(LjustNode prev) { + super(prev); + } + + @Specialization + public RubyString ljust(RubyString string, int length, @SuppressWarnings("unused") UndefinedPlaceholder padding) { + return getContext().makeString(RubyString.ljust(string.toString(), length, " ")); + } + + @Specialization + public RubyString ljust(RubyString string, int length, RubyString padding) { + return getContext().makeString(RubyString.ljust(string.toString(), length, padding.toString())); + } + + } + + @CoreMethod(names = "size", maxArgs = 0) + public abstract static class SizeNode extends CoreMethodNode { + + public SizeNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SizeNode(SizeNode prev) { + super(prev); + } + + @Specialization + public int size(RubyString string) { + return string.toString().length(); + } + } + + @CoreMethod(names = "match", minArgs = 1, maxArgs = 1) + public abstract static class MatchNode extends CoreMethodNode { + + public MatchNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public MatchNode(MatchNode prev) { + super(prev); + } + + @Specialization + public Object match(RubyString string, RubyString regexpString) { + final RubyRegexp regexp = new RubyRegexp(getContext().getCoreLibrary().getRegexpClass(), regexpString.toString()); + return regexp.match(string.toString()); + } + + @Specialization + public Object match(RubyString string, RubyRegexp regexp) { + return regexp.match(string.toString()); + } + } + + @CoreMethod(names = "rjust", minArgs = 1, maxArgs = 2) + public abstract static class RjustNode extends CoreMethodNode { + + public RjustNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public RjustNode(RjustNode prev) { + super(prev); + } + + @Specialization + public RubyString rjust(RubyString string, int length, @SuppressWarnings("unused") UndefinedPlaceholder padding) { + return getContext().makeString(RubyString.rjust(string.toString(), length, " ")); + } + + @Specialization + public RubyString rjust(RubyString string, int length, RubyString padding) { + return getContext().makeString(RubyString.rjust(string.toString(), length, padding.toString())); + } + + } + + @CoreMethod(names = "scan", minArgs = 1, maxArgs = 1) + public abstract static class ScanNode extends CoreMethodNode { + + public ScanNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ScanNode(ScanNode prev) { + super(prev); + } + + @Specialization + public RubyArray scan(RubyString string, RubyString regexp) { + return RubyString.scan(getContext(), string.toString(), Pattern.compile(regexp.toString())); + } + + @Specialization + public RubyArray scan(RubyString string, RubyRegexp regexp) { + return RubyString.scan(getContext(), string.toString(), regexp.getPattern()); + } + + } + + @CoreMethod(names = "split", minArgs = 1, maxArgs = 1) + public abstract static class SplitNode extends CoreMethodNode { + + public SplitNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SplitNode(SplitNode prev) { + super(prev); + } + + @Specialization + public RubyArray split(RubyString string, RubyString sep) { + final RubyContext context = getContext(); + + final String[] components = string.toString().split(Pattern.quote(sep.toString())); + + final Object[] objects = new Object[components.length]; + + for (int n = 0; n < objects.length; n++) { + objects[n] = context.makeString(components[n]); + } + + return RubyArray.specializedFromObjects(context.getCoreLibrary().getArrayClass(), objects); + } + + @Specialization + public RubyArray split(RubyString string, RubyRegexp sep) { + final RubyContext context = getContext(); + + final String[] components = string.toString().split(sep.getPattern().pattern()); + + final Object[] objects = new Object[components.length]; + + for (int n = 0; n < objects.length; n++) { + objects[n] = context.makeString(components[n]); + } + + return RubyArray.specializedFromObjects(context.getCoreLibrary().getArrayClass(), objects); + } + } + + @CoreMethod(names = "start_with?", minArgs = 1, maxArgs = 1) + public abstract static class StartWithNode extends CoreMethodNode { + + public StartWithNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public StartWithNode(StartWithNode prev) { + super(prev); + } + + @Specialization + public boolean endWith(RubyString string, RubyString b) { + return string.toString().startsWith(b.toString()); + } + } + + @CoreMethod(names = "to_f", maxArgs = 0) + public abstract static class ToFNode extends CoreMethodNode { + + public ToFNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToFNode(ToFNode prev) { + super(prev); + } + + @Specialization + public double toF(RubyString string) { + return Double.parseDouble(string.toString()); + } + } + + @CoreMethod(names = "to_i", maxArgs = 0) + public abstract static class ToINode extends CoreMethodNode { + + public ToINode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToINode(ToINode prev) { + super(prev); + } + + @Specialization + public Object toI(RubyString string) { + return string.toInteger(); + } + } + + @CoreMethod(names = "to_s", maxArgs = 0) + public abstract static class ToSNode extends CoreMethodNode { + + public ToSNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToSNode(ToSNode prev) { + super(prev); + } + + @Specialization + public RubyString toF(RubyString string) { + return string; + } + } + + @CoreMethod(names = {"to_sym", "intern"}, maxArgs = 0) + public abstract static class ToSymNode extends CoreMethodNode { + + public ToSymNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToSymNode(ToSymNode prev) { + super(prev); + } + + @Specialization + public RubySymbol toSym(RubyString string) { + return new RubySymbol(getContext().getCoreLibrary().getSymbolClass(), string.toString()); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/StructNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/StructNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +@CoreClass(name = "Struct") +public abstract class StructNodes { + + @CoreMethod(names = "initialize", needsBlock = true, appendCallNode = true, isSplatted = true) + public abstract static class InitalizeNode extends CoreMethodNode { + + public InitalizeNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InitalizeNode(InitalizeNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder initialize(VirtualFrame frame, RubyClass struct, Object[] args, Object block, Node callSite) { + CompilerDirectives.transferToInterpreter(); + + final RubySymbol[] symbols = new RubySymbol[args.length]; + + for (int n = 0; n < args.length; n++) { + symbols[n] = (RubySymbol) args[n]; + } + + for (RubySymbol symbol : symbols) { + ModuleNodes.AttrAccessorNode.attrAccessor(getContext(), callSite.getSourceSection(), struct, symbol.toString()); + } + + if (!RubyNilClass.isNil(block)) { + ((RubyProc) block).callWithModifiedSelf(frame.pack(), struct); + } + + return NilPlaceholder.INSTANCE; + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/SymbolNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/SymbolNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +@CoreClass(name = "Symbol") +public abstract class SymbolNodes { + + @CoreMethod(names = {"==", "==="}, minArgs = 1, maxArgs = 1) + public abstract static class EqualNode extends CoreMethodNode { + + public EqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EqualNode(EqualNode prev) { + super(prev); + } + + @Specialization + public boolean equal(@SuppressWarnings("unused") RubyString a, @SuppressWarnings("unused") NilPlaceholder b) { + return false; + } + + @Specialization + public boolean equal(RubySymbol a, RubySymbol b) { + return a.toString().equals(b.toString()); + } + + @Specialization + public boolean equal(RubySymbol a, RubyString b) { + return a.toString().equals(b.toString()); + } + + @Specialization + public boolean equal(RubySymbol a, int b) { + return a.toString().equals(Integer.toString(b)); + } + + } + + @CoreMethod(names = "empty?", maxArgs = 0) + public abstract static class EmptyNode extends CoreMethodNode { + + public EmptyNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EmptyNode(EmptyNode prev) { + super(prev); + } + + @Specialization + public boolean empty(RubySymbol symbol) { + return symbol.toString().isEmpty(); + } + + } + + @CoreMethod(names = "to_proc", maxArgs = 0) + public abstract static class ToProcNode extends CoreMethodNode { + + public ToProcNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToProcNode(ToProcNode prev) { + super(prev); + } + + @Specialization + public RubyProc toProc(RubySymbol symbol) { + // TODO(CS): this should be doing all kinds of caching + return symbol.toProc(); + } + } + + @CoreMethod(names = "to_sym", maxArgs = 0) + public abstract static class ToSymNode extends CoreMethodNode { + + public ToSymNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToSymNode(ToSymNode prev) { + super(prev); + } + + @Specialization + public RubySymbol toSym(RubySymbol symbol) { + return symbol; + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/SystemNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/SystemNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import java.io.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * Represents an expression that is evaluated by running it as a system command via forking and + * execing, and then taking stdout as a string. + */ +@NodeInfo(shortName = "system") +public class SystemNode extends RubyNode { + + @Child protected RubyNode child; + + public SystemNode(RubyContext context, SourceSection sourceSection, RubyNode child) { + super(context, sourceSection); + this.child = adoptChild(child); + } + + @Override + public Object execute(VirtualFrame frame) { + final RubyContext context = getContext(); + + final String command = child.execute(frame).toString(); + + Process process; + + try { + // We need to run via bash to get the variable and other expansion we expect + process = Runtime.getRuntime().exec(new String[]{"bash", "-c", command}); + } catch (IOException e) { + throw new RuntimeException(e); + } + + final InputStream stdout = process.getInputStream(); + final BufferedReader reader = new BufferedReader(new InputStreamReader(stdout)); + + final StringBuilder resultBuilder = new StringBuilder(); + + String line; + + // TODO(cs): this isn't great for binary output + + try { + while ((line = reader.readLine()) != null) { + resultBuilder.append(line); + resultBuilder.append("\n"); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + + return context.makeString(resultBuilder.toString()); + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ThreadNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/ThreadNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +@CoreClass(name = "Thread") +public abstract class ThreadNodes { + + @CoreMethod(names = "initialize", needsBlock = true, maxArgs = 0) + public abstract static class InitializeNode extends CoreMethodNode { + + public InitializeNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public InitializeNode(InitializeNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder initialize(RubyThread thread, RubyProc block) { + thread.initialize(block); + return NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = "join", maxArgs = 0) + public abstract static class JoinNode extends CoreMethodNode { + + public JoinNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public JoinNode(JoinNode prev) { + super(prev); + } + + @Specialization + public RubyThread join(RubyThread self) { + self.join(); + return self; + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/TimeNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/TimeNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +@CoreClass(name = "Time") +public abstract class TimeNodes { + + @CoreMethod(names = "-", minArgs = 1, maxArgs = 1) + public abstract static class SubNode extends CoreMethodNode { + + public SubNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public SubNode(SubNode prev) { + super(prev); + } + + @Specialization + public double sub(RubyTime a, RubyTime b) { + return a.subtract(b); + } + + } + + @CoreMethod(names = "now", isModuleMethod = true, needsSelf = false, maxArgs = 0) + public abstract static class NowNode extends CoreMethodNode { + + public NowNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public NowNode(NowNode prev) { + super(prev); + } + + @Specialization + public RubyTime now() { + return RubyTime.fromDate(getContext().getCoreLibrary().getTimeClass(), System.currentTimeMillis()); + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/TrueClassNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/TrueClassNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +@CoreClass(name = "TrueClass") +public abstract class TrueClassNodes { + + @CoreMethod(names = "!", needsSelf = false, maxArgs = 0) + public abstract static class NotNode extends CoreMethodNode { + + public NotNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public NotNode(NotNode prev) { + super(prev); + } + + @Specialization + public boolean not() { + return false; + } + + } + + @CoreMethod(names = {"==", "===", "=~"}, needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class EqualNode extends CoreMethodNode { + + public EqualNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EqualNode(EqualNode prev) { + super(prev); + } + + @Specialization + public boolean equal(boolean other) { + return other; + } + + @Specialization + public boolean equal(Object other) { + return other instanceof Boolean && ((boolean) other); + } + + } + + @CoreMethod(names = "^", needsSelf = false, minArgs = 1, maxArgs = 1) + public abstract static class XorNode extends CoreMethodNode { + + public XorNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public XorNode(XorNode prev) { + super(prev); + } + + @Specialization + public boolean xor(boolean other) { + return true ^ other; + } + + } + + @CoreMethod(names = "to_s", needsSelf = false, maxArgs = 0) + public abstract static class ToSNode extends CoreMethodNode { + + public ToSNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ToSNode(ToSNode prev) { + super(prev); + } + + @Specialization + public RubyString toS() { + return getContext().makeString("true"); + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/YieldingCoreMethodNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/core/YieldingCoreMethodNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.yield.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +public abstract class YieldingCoreMethodNode extends CoreMethodNode { + + @Child protected YieldDispatchNode dispatchNode; + + public YieldingCoreMethodNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + dispatchNode = adoptChild(new UninitializedYieldDispatchNode(context, getSourceSection())); + } + + public YieldingCoreMethodNode(YieldingCoreMethodNode prev) { + super(prev); + dispatchNode = adoptChild(prev.dispatchNode); + } + + public Object yield(VirtualFrame frame, RubyProc block, Object... arguments) { + return dispatchNode.dispatch(frame, block, arguments); + } + + public boolean yieldBoolean(VirtualFrame frame, RubyProc block, Object... arguments) { + return GeneralConversions.toBoolean(dispatchNode.dispatch(frame, block, arguments)); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/DebugNodes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/DebugNodes.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.debug; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; +import com.oracle.truffle.ruby.nodes.call.*; +import com.oracle.truffle.ruby.nodes.core.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +@CoreClass(name = "Debug") +public abstract class DebugNodes { + + @CoreMethod(names = "break", isModuleMethod = true, needsSelf = false, needsBlock = true, appendCallNode = true, minArgs = 0, maxArgs = 3) + public abstract static class BreakNode extends CoreMethodNode { + + public BreakNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public BreakNode(BreakNode prev) { + super(prev); + } + + @Specialization(order = 1) + public NilPlaceholder debugBreak(VirtualFrame frame, Node callNode, @SuppressWarnings("unused") UndefinedPlaceholder undefined0, @SuppressWarnings("unused") UndefinedPlaceholder undefined1, + @SuppressWarnings("unused") UndefinedPlaceholder block) { + final RubyContext context = getContext(); + if (context.getConfiguration().getDebug()) { + Node realCallNode = callNode; + while (realCallNode != null && !(realCallNode instanceof CallNode)) { + realCallNode = realCallNode.getParent(); + } + context.getDebugManager().haltedAt(realCallNode, frame.materialize()); + } + return NilPlaceholder.INSTANCE; + } + + @Specialization(order = 2) + public NilPlaceholder debugBreak(RubyString fileName, int line, @SuppressWarnings("unused") Node callNode, @SuppressWarnings("unused") UndefinedPlaceholder block) { + final RubyContext context = getContext(); + if (context.getConfiguration().getDebug()) { + final Source source = context.getSourceManager().get(fileName.toString()); + final SourceLineLocation lineLocation = new SourceLineLocation(source, line); + context.getDebugManager().setBreakpoint(lineLocation); + } + return NilPlaceholder.INSTANCE; + } + + @Specialization(order = 3) + public NilPlaceholder debugBreak(RubyString fileName, int line, @SuppressWarnings("unused") Node callNode, RubyProc block) { + final RubyContext context = getContext(); + if (context.getConfiguration().getDebug()) { + final Source source = context.getSourceManager().get(fileName.toString()); + final SourceLineLocation lineLocation = new SourceLineLocation(source, line); + context.getDebugManager().setLineProc(lineLocation, block); + } + return NilPlaceholder.INSTANCE; + } + + @Specialization(order = 4) + public NilPlaceholder debugBreak(RubySymbol methodName, RubySymbol localName, @SuppressWarnings("unused") Node callNode, @SuppressWarnings("unused") UndefinedPlaceholder block) { + final RubyContext context = getContext(); + if (context.getConfiguration().getDebug()) { + final RubyMethod method = context.getCoreLibrary().getMainObject().getLookupNode().lookupMethod(methodName.toString()); + context.getDebugManager().setLocalBreak(method.getUniqueIdentifier(), localName.toString()); + } + return NilPlaceholder.INSTANCE; + } + + @Specialization(order = 5) + public NilPlaceholder debugBreak(RubySymbol methodName, RubySymbol localName, @SuppressWarnings("unused") Node callNode, RubyProc block) { + final RubyContext context = getContext(); + if (context.getConfiguration().getDebug()) { + final RubyMethod method = context.getCoreLibrary().getMainObject().getLookupNode().lookupMethod(methodName.toString()); + context.getDebugManager().setLocalProc(method.getUniqueIdentifier(), localName.toString(), block); + } + return NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = "continue", isModuleMethod = true, needsSelf = false, maxArgs = 0) + public abstract static class ContinueNode extends CoreMethodNode { + + public ContinueNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public ContinueNode(ContinueNode prev) { + super(prev); + } + + @Specialization + public Object debugContinue() { + if (getContext().getConfiguration().getDebug()) { + throw new BreakShellException(); + } + return NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = "enabled?", isModuleMethod = true, needsSelf = false, maxArgs = 0) + public abstract static class EnabledNode extends CoreMethodNode { + + public EnabledNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public EnabledNode(ContinueNode prev) { + super(prev); + } + + @Specialization + public boolean enabled() { + return getContext().getConfiguration().getDebug(); + } + + } + + @CoreMethod(names = "where", isModuleMethod = true, needsSelf = false, appendCallNode = true, minArgs = 1, maxArgs = 1) + public abstract static class WhereNode extends CoreMethodNode { + + public WhereNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public WhereNode(WhereNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder where(Node callNode) { + final RubyContext context = getContext(); + if (context.getConfiguration().getDebug()) { + context.getConfiguration().getStandardOut().println(callNode.getSourceSection()); + } + return NilPlaceholder.INSTANCE; + } + + } + + @CoreMethod(names = "remove", isModuleMethod = true, needsSelf = false, needsBlock = true, minArgs = 2, maxArgs = 2) + public abstract static class RemoveNode extends CoreMethodNode { + + public RemoveNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + public RemoveNode(RemoveNode prev) { + super(prev); + } + + @Specialization + public NilPlaceholder debugRemove(RubyString fileName, int line) { + final RubyContext context = getContext(); + if (context.getConfiguration().getDebug()) { + final Source source = context.getSourceManager().get(fileName.toString()); + final SourceLineLocation lineLocation = new SourceLineLocation(source, line); + context.getDebugManager().removeBreakpoint(lineLocation); + } + return NilPlaceholder.INSTANCE; + } + + @Specialization + public NilPlaceholder debugRemove(RubySymbol methodName, RubySymbol localName) { + final RubyContext context = getContext(); + if (context.getConfiguration().getDebug()) { + final RubyMethod method = context.getCoreLibrary().getMainObject().getLookupNode().lookupMethod(methodName.toString()); + context.getDebugManager().removeLocalProbe(method.getUniqueIdentifier(), localName.toString()); + } + return NilPlaceholder.INSTANCE; + } + + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/RubyProxyNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/debug/RubyProxyNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.debug; + +import java.math.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.instrument.*; +import com.oracle.truffle.api.nodes.instrument.InstrumentationProbeNode.ProbeChain; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +/** + * An instrumentation proxy node that forwards all Ruby execution calls through to + * a child node and returns results back to the parent, but which also sends notifications to an + * attached {@linkplain ProbeChain chain} of {@linkplain InstrumentationProbeNode probes}. + */ +public class RubyProxyNode extends RubyNode implements InstrumentationProxyNode { + + @Child private RubyNode child; + + private final ProbeChain probeChain; + + public RubyProxyNode(RubyContext context, RubyNode child) { + super(context, SourceSection.NULL); + this.child = adoptChild(child); + assert !(child instanceof RubyProxyNode); + this.probeChain = new ProbeChain(child.getSourceSection(), null); + } + + @Override + public RubyNode getNonProxyNode() { + return child; + } + + public RubyNode getChild() { + return child; + } + + public ProbeChain getProbeChain() { + return probeChain; + } + + @Override + public Object execute(VirtualFrame frame) { + probeChain.notifyEnter(child, frame); + + Object result; + + try { + result = child.execute(frame); + probeChain.notifyLeave(child, frame, result); + } catch (Exception e) { + probeChain.notifyLeaveExceptional(child, frame, e); + throw (e); + } + + return result; + } + + @Override + public RubyArray executeArray(VirtualFrame frame) throws UnexpectedResultException { + probeChain.notifyEnter(child, frame); + + RubyArray result; + + try { + result = child.executeArray(frame); + probeChain.notifyLeave(child, frame, result); + } catch (Exception e) { + probeChain.notifyLeaveExceptional(child, frame, e); + throw (e); + } + + return result; + } + + @Override + public BigInteger executeBignum(VirtualFrame frame) throws UnexpectedResultException { + probeChain.notifyEnter(child, frame); + + BigInteger result; + + try { + result = child.executeBignum(frame); + probeChain.notifyLeave(child, frame, result); + } catch (Exception e) { + probeChain.notifyLeaveExceptional(child, frame, e); + throw (e); + } + + return result; + } + + @Override + public boolean executeBoolean(VirtualFrame frame) throws UnexpectedResultException { + probeChain.notifyEnter(child, frame); + + boolean result; + + try { + result = child.executeBoolean(frame); + probeChain.notifyLeave(child, frame, result); + } catch (Exception e) { + probeChain.notifyLeaveExceptional(child, frame, e); + throw (e); + } + + return result; + } + + @Override + public Object isDefined(VirtualFrame frame) { + return child.isDefined(frame); + } + + @Override + public int executeFixnum(VirtualFrame frame) throws UnexpectedResultException { + probeChain.notifyEnter(child, frame); + + int result; + + try { + result = child.executeFixnum(frame); + probeChain.notifyLeave(child, frame, result); + } catch (Exception e) { + probeChain.notifyLeaveExceptional(child, frame, e); + throw (e); + } + + return result; + } + + @Override + public double executeFloat(VirtualFrame frame) throws UnexpectedResultException { + probeChain.notifyEnter(child, frame); + + double result; + + try { + result = child.executeFloat(frame); + probeChain.notifyLeave(child, frame, result); + } catch (Exception e) { + probeChain.notifyLeaveExceptional(child, frame, e); + throw (e); + } + + return result; + } + + @Override + public RubyString executeString(VirtualFrame frame) throws UnexpectedResultException { + probeChain.notifyEnter(child, frame); + + RubyString result; + + try { + result = child.executeString(frame); + probeChain.notifyLeave(child, frame, result); + } catch (Exception e) { + probeChain.notifyLeaveExceptional(child, frame, e); + throw (e); + } + + return result; + } + + @Override + public void executeVoid(VirtualFrame frame) { + probeChain.notifyEnter(child, frame); + + try { + child.executeVoid(frame); + probeChain.notifyLeave(child, frame); + } catch (Exception e) { + probeChain.notifyLeaveExceptional(child, frame, e); + throw (e); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/BignumLiteralNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/BignumLiteralNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.literal; + +import java.math.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +@NodeInfo(shortName = "bignum") +public class BignumLiteralNode extends RubyNode { + + private final BigInteger value; + + public BignumLiteralNode(RubyContext context, SourceSection sourceSection, BigInteger value) { + super(context, sourceSection); + this.value = value; + } + + @Override + public BigInteger executeBignum(VirtualFrame frame) { + return value; + } + + @Override + public Object execute(VirtualFrame frame) { + return value; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/BooleanLiteralNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/BooleanLiteralNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.literal; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +@NodeInfo(shortName = "boolean") +public class BooleanLiteralNode extends RubyNode { + + private final boolean value; + + public BooleanLiteralNode(RubyContext context, SourceSection sourceSection, boolean value) { + super(context, sourceSection); + this.value = value; + } + + @Override + public Object execute(VirtualFrame frame) { + return executeBoolean(frame); + } + + @Override + public boolean executeBoolean(VirtualFrame frame) { + return value; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/FixnumLiteralNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/FixnumLiteralNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.literal; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +@NodeInfo(shortName = "fixnum") +public class FixnumLiteralNode extends RubyNode { + + private final int value; + + public FixnumLiteralNode(RubyContext context, SourceSection sourceSection, int value) { + super(context, sourceSection); + this.value = value; + } + + @Override + public Object execute(VirtualFrame frame) { + return executeFixnum(frame); + } + + @Override + public int executeFixnum(VirtualFrame frame) { + return value; + } + + // TODO(CS): remove this - shouldn't be fiddling with nodes from the outside + public int getValue() { + return value; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/FloatLiteralNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/FloatLiteralNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.literal; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +@NodeInfo(shortName = "float") +public class FloatLiteralNode extends RubyNode { + + private final double value; + + public FloatLiteralNode(RubyContext context, SourceSection sourceSection, double value) { + super(context, sourceSection); + this.value = value; + } + + @Override + public Object execute(VirtualFrame frame) { + return executeFloat(frame); + } + + @Override + public double executeFloat(VirtualFrame frame) { + return value; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/HashLiteralNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/HashLiteralNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.literal; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +@NodeInfo(shortName = "hash") +public class HashLiteralNode extends RubyNode { + + @Children protected final RubyNode[] keys; + @Children protected final RubyNode[] values; + + public HashLiteralNode(SourceSection sourceSection, RubyNode[] keys, RubyNode[] values, RubyContext context) { + super(context, sourceSection); + assert keys.length == values.length; + this.keys = adoptChildren(keys); + this.values = adoptChildren(values); + } + + @ExplodeLoop + @Override + public Object execute(VirtualFrame frame) { + final RubyHash hash = new RubyHash(getContext().getCoreLibrary().getHashClass()); + + for (int n = 0; n < keys.length; n++) { + hash.put(keys[n].execute(frame), values[n].execute(frame)); + } + + return hash; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/NilNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/NilNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.literal; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * A node that does nothing and evaluates to Nil. A no-op. + */ +@NodeInfo(shortName = "nil") +public final class NilNode extends RubyNode { + + public NilNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + @Override + public NilPlaceholder executeNilPlaceholder(VirtualFrame frame) { + return NilPlaceholder.INSTANCE; + } + + @Override + public Object execute(VirtualFrame frame) { + return executeNilPlaceholder(frame); + } + + @Override + public void executeVoid(VirtualFrame frame) { + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/ObjectLiteralNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/ObjectLiteralNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.literal; + +import java.math.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +@NodeInfo(shortName = "object") +public class ObjectLiteralNode extends RubyNode { + + private final Object object; + + public ObjectLiteralNode(RubyContext context, SourceSection sourceSection, Object object) { + super(context, sourceSection); + + assert RubyContext.shouldObjectBeVisible(object); + assert !(object instanceof Integer); + assert !(object instanceof Double); + assert !(object instanceof BigInteger); + assert !(object instanceof String); + assert !(object instanceof RubyString); + + this.object = object; + } + + @Override + public Object execute(VirtualFrame frame) { + return object; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/RangeLiteralNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/RangeLiteralNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.literal; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.range.*; + +@NodeInfo(shortName = "range") +@NodeChildren({@NodeChild("begin"), @NodeChild("end")}) +public abstract class RangeLiteralNode extends RubyNode { + + private final boolean excludeEnd; + + public RangeLiteralNode(RubyContext context, SourceSection sourceSection, boolean excludeEnd) { + super(context, sourceSection); + this.excludeEnd = excludeEnd; + } + + public RangeLiteralNode(RangeLiteralNode prev) { + this(prev.getContext(), prev.getSourceSection(), prev.excludeEnd); + } + + @Specialization + public FixnumRange doFixnum(int begin, int end) { + return new FixnumRange(getContext().getCoreLibrary().getRangeClass(), begin, end, excludeEnd); + } + + @Generic + public Object doGeneric(Object begin, Object end) { + final RubyContext context = getContext(); + + if ((begin instanceof Integer) && (end instanceof Integer)) { + return doFixnum((int) begin, (int) end); + } else { + return new ObjectRange(context.getCoreLibrary().getRangeClass(), begin, end, excludeEnd); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/StringLiteralNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/StringLiteralNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.literal; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +@NodeInfo(shortName = "string") +public class StringLiteralNode extends RubyNode { + + private final String string; + + public StringLiteralNode(RubyContext context, SourceSection sourceSection, String string) { + super(context, sourceSection); + + assert string != null; + + this.string = string; + } + + @Override + public Object execute(VirtualFrame frame) { + return getContext().makeString(string); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/array/ArrayLiteralNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/array/ArrayLiteralNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.literal.array; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +public abstract class ArrayLiteralNode extends RubyNode { + + @Children protected final RubyNode[] values; + + public ArrayLiteralNode(RubyContext context, SourceSection sourceSection, RubyNode[] values) { + super(context, sourceSection); + this.values = adoptChildren(values); + } + + protected RubyArray makeGeneric(VirtualFrame frame, Object[] alreadyExecuted) { + CompilerAsserts.neverPartOfCompilation(); + + replace(new ObjectArrayLiteralNode(getContext(), getSourceSection(), values)); + + final Object[] executedValues = new Object[values.length]; + + for (int n = 0; n < values.length; n++) { + if (n < alreadyExecuted.length) { + executedValues[n] = alreadyExecuted[n]; + } else { + executedValues[n] = values[n].execute(frame); + } + } + + return RubyArray.specializedFromObjects(getContext().getCoreLibrary().getArrayClass(), executedValues); + } + + @Override + public Object isDefined(VirtualFrame frame) { + return getContext().makeString("expression"); + } + + // TODO(CS): remove this - shouldn't be fiddling with nodes from the outside + public RubyNode[] getValues() { + return values; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/array/FixnumArrayLiteralNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/array/FixnumArrayLiteralNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.literal.array; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +@NodeInfo(shortName = "fixnum-array-literal") +public class FixnumArrayLiteralNode extends ArrayLiteralNode { + + public FixnumArrayLiteralNode(RubyContext context, SourceSection sourceSection, RubyNode[] values) { + super(context, sourceSection, values); + } + + @ExplodeLoop + @Override + public RubyArray executeArray(VirtualFrame frame) { + final int[] executedValues = new int[values.length]; + + for (int n = 0; n < values.length; n++) { + try { + executedValues[n] = values[n].executeFixnum(frame); + } catch (UnexpectedResultException e) { + final Object[] executedObjects = new Object[n]; + + for (int i = 0; i < n; i++) { + executedObjects[i] = executedValues[i]; + } + + return makeGeneric(frame, executedObjects); + } + } + + return new RubyArray(getContext().getCoreLibrary().getArrayClass(), new FixnumArrayStore(executedValues)); + } + + @ExplodeLoop + @Override + public void executeVoid(VirtualFrame frame) { + for (int n = 0; n < values.length; n++) { + values[n].executeVoid(frame); + } + } + + @Override + public Object execute(VirtualFrame frame) { + return executeArray(frame); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/array/ObjectArrayLiteralNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/array/ObjectArrayLiteralNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.literal.array; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +@NodeInfo(shortName = "object-array-literal") +public class ObjectArrayLiteralNode extends ArrayLiteralNode { + + public ObjectArrayLiteralNode(RubyContext context, SourceSection sourceSection, RubyNode[] values) { + super(context, sourceSection, values); + } + + @ExplodeLoop + @Override + public RubyArray executeArray(VirtualFrame frame) { + final Object[] executedValues = new Object[values.length]; + + for (int n = 0; n < values.length; n++) { + executedValues[n] = values[n].execute(frame); + } + + return new RubyArray(getContext().getCoreLibrary().getArrayClass(), new ObjectArrayStore(executedValues)); + } + + @ExplodeLoop + @Override + public void executeVoid(VirtualFrame frame) { + for (int n = 0; n < values.length; n++) { + values[n].executeVoid(frame); + } + } + + @Override + public Object execute(VirtualFrame frame) { + return executeArray(frame); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/array/UninitialisedArrayLiteralNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/literal/array/UninitialisedArrayLiteralNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.literal.array; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +@NodeInfo(shortName = "uninit-array-literal") +public class UninitialisedArrayLiteralNode extends ArrayLiteralNode { + + public UninitialisedArrayLiteralNode(RubyContext context, SourceSection sourceSection, RubyNode[] values) { + super(context, sourceSection, values); + } + + @ExplodeLoop + @Override + public Object execute(VirtualFrame frame) { + CompilerDirectives.transferToInterpreter(); + + final Object[] executedValues = new Object[values.length]; + + for (int n = 0; n < values.length; n++) { + executedValues[n] = values[n].execute(frame); + } + + final RubyArray array = RubyArray.specializedFromObjects(getContext().getCoreLibrary().getArrayClass(), executedValues); + final ArrayStore store = array.getArrayStore(); + + if (store instanceof FixnumArrayStore) { + replace(new FixnumArrayLiteralNode(getContext(), getSourceSection(), values)); + } else { + replace(new ObjectArrayLiteralNode(getContext(), getSourceSection(), values)); + } + + return array; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/AddMethodNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/AddMethodNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +@NodeInfo(shortName = "add-method") +public class AddMethodNode extends RubyNode { + + @Child protected RubyNode receiver; + @Child protected MethodDefinitionNode method; + + public AddMethodNode(RubyContext context, SourceSection section, RubyNode receiver, MethodDefinitionNode method) { + super(context, section); + this.receiver = adoptChild(receiver); + this.method = adoptChild(method); + } + + @Override + public Object execute(VirtualFrame frame) { + final Object receiverObject = receiver.execute(frame); + + final RubyMethod methodObject = (RubyMethod) method.execute(frame); + + final FrameSlot moduleFunctionFlagSlot = frame.getFrameDescriptor().findFrameSlot(RubyModule.MODULE_FUNCTION_FLAG_FRAME_SLOT_ID); + + boolean moduleFunctionFlag; + + if (moduleFunctionFlagSlot == null) { + moduleFunctionFlag = false; + } else { + Object moduleFunctionObject; + + try { + moduleFunctionObject = frame.getObject(moduleFunctionFlagSlot); + } catch (FrameSlotTypeException e) { + throw new RuntimeException(e); + } + + if (moduleFunctionObject instanceof Boolean) { + moduleFunctionFlag = (boolean) moduleFunctionObject; + } else { + moduleFunctionFlag = false; + } + } + + final RubyModule module = (RubyModule) receiverObject; + + final RubyMethod methodWithDeclaringModule = methodObject.withDeclaringModule(module); + + module.addMethod(methodWithDeclaringModule); + + if (moduleFunctionFlag) { + module.getSingletonClass().addMethod(methodWithDeclaringModule); + } + + return NilPlaceholder.INSTANCE; + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/AliasNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/AliasNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +@NodeInfo(shortName = "alias") +public class AliasNode extends RubyNode { + + @Child protected RubyNode module; + final String newName; + final String oldName; + + public AliasNode(RubyContext context, SourceSection sourceSection, RubyNode module, String newName, String oldName) { + super(context, sourceSection); + this.module = adoptChild(module); + this.newName = newName; + this.oldName = oldName; + } + + @Override + public void executeVoid(VirtualFrame frame) { + final RubyModule moduleObject = (RubyModule) module.execute(frame); + moduleObject.alias(newName, oldName); + } + + @Override + public Object execute(VirtualFrame frame) { + executeVoid(frame); + return NilPlaceholder.INSTANCE; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/BlockDefinitionNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/BlockDefinitionNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +/** + * Define a block. That is, store the definition of a block and when executed produce the executable + * object that results. + */ +@NodeInfo(shortName = "block-def") +public class BlockDefinitionNode extends MethodDefinitionNode { + + public BlockDefinitionNode(RubyContext context, SourceSection sourceSection, String name, UniqueMethodIdentifier uniqueIdentifier, FrameDescriptor frameDescriptor, + boolean requiresDeclarationFrame, RubyRootNode pristineRootNode, CallTarget callTarget) { + super(context, sourceSection, name, uniqueIdentifier, frameDescriptor, requiresDeclarationFrame, pristineRootNode, callTarget); + } + + @Override + public Object execute(VirtualFrame frame) { + final RubyContext context = getContext(); + + MaterializedFrame declarationFrame; + + if (requiresDeclarationFrame) { + declarationFrame = frame.materialize(); + } else { + declarationFrame = null; + } + + final RubyArguments arguments = frame.getArguments(RubyArguments.class); + + final InlinableMethodImplementation methodImplementation = new InlinableMethodImplementation(callTarget, declarationFrame, frameDescriptor, pristineRootNode, true, false); + final RubyMethod method = new RubyMethod(getSourceSection(), null, uniqueIdentifier, null, name, Visibility.PUBLIC, false, methodImplementation); + + return new RubyProc(context.getCoreLibrary().getProcClass(), RubyProc.Type.PROC, arguments.getSelf(), arguments.getBlock(), method); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/CatchNextNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/CatchNextNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.utilities.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; + +/** + * Catch a {@code next} jump at the root of a method. + */ +public class CatchNextNode extends RubyNode { + + @Child protected RubyNode body; + + private final BranchProfile nextProfile = new BranchProfile(); + + public CatchNextNode(RubyContext context, SourceSection sourceSection, RubyNode body) { + super(context, sourceSection); + this.body = adoptChild(body); + } + + @Override + public Object execute(VirtualFrame frame) { + try { + return body.execute(frame); + } catch (NextException e) { + nextProfile.enter(); + return NilPlaceholder.INSTANCE; + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/CatchReturnAsErrorNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/CatchReturnAsErrorNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; + +/** + * Catch a {@code return} jump at the root of a method, and report it as an error. + */ +public class CatchReturnAsErrorNode extends RubyNode { + + @Child protected RubyNode body; + + public CatchReturnAsErrorNode(RubyContext context, SourceSection sourceSection, RubyNode body) { + super(context, sourceSection); + this.body = adoptChild(body); + } + + @Override + public Object execute(VirtualFrame frame) { + try { + return body.execute(frame); + } catch (ReturnException e) { + CompilerDirectives.transferToInterpreter(); + throw new RaiseException(getContext().getCoreLibrary().unexpectedReturn()); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/CatchReturnNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/CatchReturnNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.utilities.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; + +/** + * Catch a {@code return} jump at the root of a method. + */ +public class CatchReturnNode extends RubyNode { + + @Child protected RubyNode body; + private final long returnID; + + private final BranchProfile returnProfile = new BranchProfile(); + private final BranchProfile returnToOtherMethodProfile = new BranchProfile(); + + public CatchReturnNode(RubyContext context, SourceSection sourceSection, RubyNode body, long returnID) { + super(context, sourceSection); + this.body = adoptChild(body); + this.returnID = returnID; + } + + public CatchReturnNode(CatchReturnNode prev) { + super(prev); + returnID = prev.returnID; + } + + @Override + public Object execute(VirtualFrame frame) { + try { + return body.execute(frame); + } catch (ReturnException e) { + returnProfile.enter(); + + if (e.getReturnID() == returnID) { + return e.getValue(); + } else { + returnToOtherMethodProfile.enter(); + throw e; + } + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/MethodDefinitionNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/MethodDefinitionNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +/** + * Define a method. That is, store the definition of a method and when executed produce the + * executable object that results. + */ +@NodeInfo(shortName = "method-def") +public class MethodDefinitionNode extends RubyNode { + + protected final String name; + protected final UniqueMethodIdentifier uniqueIdentifier; + + protected final FrameDescriptor frameDescriptor; + protected final RubyRootNode pristineRootNode; + + protected final CallTarget callTarget; + + protected final boolean requiresDeclarationFrame; + + public MethodDefinitionNode(RubyContext context, SourceSection sourceSection, String name, UniqueMethodIdentifier uniqueIdentifier, FrameDescriptor frameDescriptor, + boolean requiresDeclarationFrame, RubyRootNode pristineRootNode, CallTarget callTarget) { + super(context, sourceSection); + this.name = name; + this.uniqueIdentifier = uniqueIdentifier; + this.frameDescriptor = frameDescriptor; + this.requiresDeclarationFrame = requiresDeclarationFrame; + this.pristineRootNode = pristineRootNode; + this.callTarget = callTarget; + } + + public RubyMethod executeMethod(VirtualFrame frame) { + CompilerDirectives.transferToInterpreter(); + + MaterializedFrame declarationFrame; + + if (requiresDeclarationFrame) { + declarationFrame = frame.materialize(); + } else { + declarationFrame = null; + } + + final FrameSlot visibilitySlot = frame.getFrameDescriptor().findFrameSlot(RubyModule.VISIBILITY_FRAME_SLOT_ID); + + Visibility visibility; + + if (visibilitySlot == null) { + visibility = Visibility.PUBLIC; + } else { + Object visibilityObject; + + try { + visibilityObject = frame.getObject(visibilitySlot); + } catch (FrameSlotTypeException e) { + throw new RuntimeException(e); + } + + if (visibilityObject instanceof Visibility) { + visibility = (Visibility) visibilityObject; + } else { + visibility = Visibility.PUBLIC; + } + } + + final InlinableMethodImplementation methodImplementation = new InlinableMethodImplementation(callTarget, declarationFrame, frameDescriptor, pristineRootNode, false, false); + return new RubyMethod(getSourceSection(), null, uniqueIdentifier, null, name, visibility, false, methodImplementation); + } + + @Override + public Object execute(VirtualFrame frame) { + return executeMethod(frame); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/ShellResultNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/ShellResultNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * Produce a {@link ShellResult} object from a return value and the resulting frame. + */ +public class ShellResultNode extends RubyNode { + + @Child protected RubyNode body; + + public ShellResultNode(RubyContext context, SourceSection sourceSection, RubyNode body) { + super(context, sourceSection); + this.body = adoptChild(body); + } + + @Override + public Object execute(VirtualFrame frame) { + return new ShellResult(body.execute(frame), frame.materialize()); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/arguments/BlockDestructureSwitchNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/arguments/BlockDestructureSwitchNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods.arguments; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +/** + * Switches between loading arguments as normal and doing a destructure. See + * testBlockArgumentsDestructure and MethodTranslator. + */ +@NodeInfo(shortName = "block-destructure-switch") +public class BlockDestructureSwitchNode extends RubyNode { + + @Child protected RubyNode loadIndividualArguments; + @Child protected RubyNode destructureArguments; + @Child protected RubyNode body; + + public BlockDestructureSwitchNode(RubyContext context, SourceSection sourceSection, RubyNode loadIndividualArguments, RubyNode destructureArguments, RubyNode body) { + super(context, sourceSection); + this.loadIndividualArguments = adoptChild(loadIndividualArguments); + this.destructureArguments = adoptChild(destructureArguments); + this.body = adoptChild(body); + } + + @Override + public Object execute(VirtualFrame frame) { + final RubyArguments arguments = frame.getArguments(RubyArguments.class); + + if (arguments.getArguments().length == 1 && arguments.getArguments()[0] instanceof RubyArray) { + destructureArguments.executeVoid(frame); + } else { + loadIndividualArguments.executeVoid(frame); + } + + return body.execute(frame); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/arguments/CheckArityNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/arguments/CheckArityNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods.arguments; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +/** + * Check arguments meet the arity of the method. + */ +@NodeInfo(shortName = "check-arity") +public class CheckArityNode extends RubyNode { + + private final Arity arity; + + public CheckArityNode(RubyContext context, SourceSection sourceSection, Arity arity) { + super(context, sourceSection); + this.arity = arity; + } + + @Override + public void executeVoid(VirtualFrame frame) { + final RubyArguments arguments = frame.getArguments(RubyArguments.class); + arity.checkArguments(getContext(), arguments.getArguments()); + } + + @Override + public Object execute(VirtualFrame frame) { + executeVoid(frame); + return NilPlaceholder.INSTANCE; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/arguments/ReadAllArgumentsNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/arguments/ReadAllArgumentsNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods.arguments; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +public class ReadAllArgumentsNode extends RubyNode { + + public ReadAllArgumentsNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + @Override + public Object[] executeObjectArray(VirtualFrame frame) { + return frame.getArguments(RubyArguments.class).getArguments(); + } + + @Override + public Object execute(VirtualFrame frame) { + return executeObjectArray(frame); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/arguments/ReadBlockArgumentNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/arguments/ReadBlockArgumentNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods.arguments; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * Read the block as a {@code Proc}. + */ +@NodeInfo(shortName = "read-block-argument") +public class ReadBlockArgumentNode extends RubyNode { + + private final boolean undefinedIfNotPresent; + + public ReadBlockArgumentNode(RubyContext context, SourceSection sourceSection, boolean undefinedIfNotPresent) { + super(context, sourceSection); + this.undefinedIfNotPresent = undefinedIfNotPresent; + } + + @Override + public Object execute(VirtualFrame frame) { + final RubyArguments arguments = frame.getArguments(RubyArguments.class); + final RubyProc block = arguments.getBlock(); + + if (block == null) { + if (undefinedIfNotPresent) { + return UndefinedPlaceholder.INSTANCE; + } else { + return NilPlaceholder.INSTANCE; + } + } else { + return block; + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/arguments/ReadDestructureArgumentNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/arguments/ReadDestructureArgumentNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods.arguments; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +/** + * Assuming argument 0 is an array, read an element from that array. + */ +@NodeInfo(shortName = "read-destructure-argument") +public class ReadDestructureArgumentNode extends RubyNode { + + private final int index; + + public ReadDestructureArgumentNode(RubyContext context, SourceSection sourceSection, int index) { + super(context, sourceSection); + this.index = index; + } + + @Override + public Object execute(VirtualFrame frame) { + final RubyArray array = (RubyArray) frame.getArguments(RubyArguments.class).getArguments()[0]; + return array.get(index); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/arguments/ReadOptionalArgumentNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/arguments/ReadOptionalArgumentNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods.arguments; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.utilities.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * Read an optional argument. + */ +@NodeInfo(shortName = "read-optional-argument") +public class ReadOptionalArgumentNode extends RubyNode { + + private final int index; + private final int minimum; + @Child protected RubyNode defaultValue; + + private final BranchProfile defaultValueProfile = new BranchProfile(); + + public ReadOptionalArgumentNode(RubyContext context, SourceSection sourceSection, int index, int minimum, RubyNode defaultValue) { + super(context, sourceSection); + this.index = index; + this.minimum = minimum; + this.defaultValue = adoptChild(defaultValue); + } + + @Override + public Object execute(VirtualFrame frame) { + final Object[] arguments = frame.getArguments(RubyArguments.class).getArguments(); + + if (arguments.length < minimum) { + defaultValueProfile.enter(); + return defaultValue.execute(frame); + } else { + assert index < arguments.length; + return arguments[index]; + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/arguments/ReadPostArgumentNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/arguments/ReadPostArgumentNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods.arguments; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * Read a post-optional argument. + */ +@NodeInfo(shortName = "read-post-optional-argument") +public class ReadPostArgumentNode extends RubyNode { + + private final int indexFromEnd; + + public ReadPostArgumentNode(RubyContext context, SourceSection sourceSection, int indexFromEnd) { + super(context, sourceSection); + this.indexFromEnd = indexFromEnd; + } + + @Override + public Object execute(VirtualFrame frame) { + final Object[] arguments = frame.getArguments(RubyArguments.class).getArguments(); + final int effectiveIndex = arguments.length - 1 - indexFromEnd; + assert effectiveIndex < arguments.length; + return arguments[effectiveIndex]; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/arguments/ReadPreArgumentNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/arguments/ReadPreArgumentNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods.arguments; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.utilities.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * Read pre-optional argument. + */ +@NodeInfo(shortName = "read-pre-optional-argument") +public class ReadPreArgumentNode extends RubyNode { + + private final int index; + private final boolean undefinedIfNotPresent; + + private final BranchProfile notPresentProfile = new BranchProfile(); + + public ReadPreArgumentNode(RubyContext context, SourceSection sourceSection, int index, boolean undefinedIfNotPresent) { + super(context, sourceSection); + this.index = index; + this.undefinedIfNotPresent = undefinedIfNotPresent; + } + + @Override + public Object execute(VirtualFrame frame) { + final Object[] arguments = frame.getArguments(RubyArguments.class).getArguments(); + + if (undefinedIfNotPresent) { + if (index >= arguments.length) { + notPresentProfile.enter(); + return UndefinedPlaceholder.INSTANCE; + } + } else { + assert index < arguments.length; + } + + return arguments[index]; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/arguments/ReadRestArgumentNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/arguments/ReadRestArgumentNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods.arguments; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +/** + * Read the rest of arguments after a certain point into an array. + */ +@NodeInfo(shortName = "read-rest-of-arguments") +public class ReadRestArgumentNode extends RubyNode { + + private final int index; + + public ReadRestArgumentNode(RubyContext context, SourceSection sourceSection, int index) { + super(context, sourceSection); + this.index = index; + } + + @Override + public Object execute(VirtualFrame frame) { + final RubyArguments rubyArguments = frame.getArguments(RubyArguments.class); + + final Object[] arguments = rubyArguments.getArguments(); + + final RubyClass arrayClass = getContext().getCoreLibrary().getArrayClass(); + + if (arguments.length <= index) { + return new RubyArray(arrayClass); + } else if (index == 0) { + return new RubyArray(arrayClass, new ObjectArrayStore(arguments)); + } else { + return new RubyArray(arrayClass, new ObjectArrayStore(Arrays.copyOfRange(arguments, index, arguments.length))); + } + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/locals/FlipFlopStateNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/locals/FlipFlopStateNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods.locals; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public abstract class FlipFlopStateNode extends Node { + + public FlipFlopStateNode(SourceSection sourceSection) { + super(sourceSection); + } + + public abstract boolean getState(VirtualFrame frame); + + public abstract void setState(VirtualFrame frame, boolean state); + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/locals/FrameSlotNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/locals/FrameSlotNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods.locals; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +public abstract class FrameSlotNode extends RubyNode { + + protected final FrameSlot frameSlot; + + protected FrameSlotNode(RubyContext context, SourceSection sourceSection, FrameSlot frameSlot) { + super(context, sourceSection); + this.frameSlot = frameSlot; + } + + public final FrameSlot getFrameSlot() { + return frameSlot; + } + + @Override + public FrameSlotNode copy() { + return (FrameSlotNode) super.copy(); + } + + protected final void setBoolean(Frame frame, boolean value) { + frame.setBoolean(frameSlot, value); + } + + protected final void setFixnum(Frame frame, int value) { + frame.setInt(frameSlot, value); + } + + protected final void setFloat(Frame frame, double value) { + frame.setDouble(frameSlot, value); + } + + protected final void setObject(Frame frame, Object value) { + frame.setObject(frameSlot, value); + } + + protected final boolean getBoolean(Frame frame) throws FrameSlotTypeException { + return frame.getBoolean(frameSlot); + } + + protected final int getFixnum(Frame frame) throws FrameSlotTypeException { + return frame.getInt(frameSlot); + } + + protected final double getFloat(Frame frame) throws FrameSlotTypeException { + return frame.getDouble(frameSlot); + } + + protected final Object getObject(Frame frame) { + try { + return frame.getObject(frameSlot); + } catch (FrameSlotTypeException e) { + throw new IllegalStateException(); + } + } + + protected final boolean isBooleanKind() { + return isKind(FrameSlotKind.Boolean); + } + + protected final boolean isFixnumKind() { + return isKind(FrameSlotKind.Int); + } + + protected final boolean isFloatKind() { + return isKind(FrameSlotKind.Double); + } + + protected final boolean isObjectKind() { + if (frameSlot.getKind() != FrameSlotKind.Object) { + CompilerDirectives.transferToInterpreter(); + frameSlot.setKind(FrameSlotKind.Object); + } + return true; + } + + private boolean isKind(FrameSlotKind kind) { + return frameSlot.getKind() == kind || initialSetKind(kind); + } + + private boolean initialSetKind(FrameSlotKind kind) { + if (frameSlot.getKind() == FrameSlotKind.Illegal) { + CompilerDirectives.transferToInterpreter(); + frameSlot.setKind(kind); + return true; + } + return false; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/locals/InitFlipFlopSlotNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/locals/InitFlipFlopSlotNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods.locals; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +public class InitFlipFlopSlotNode extends RubyNode { + + private final FrameSlot frameSlot; + + public InitFlipFlopSlotNode(RubyContext context, SourceSection sourceSection, FrameSlot frameSlot) { + super(context, sourceSection); + this.frameSlot = frameSlot; + } + + @Override + public void executeVoid(VirtualFrame frame) { + frame.setBoolean(frameSlot, false); + } + + @Override + public Object execute(VirtualFrame frame) { + executeVoid(frame); + return null; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/locals/LevelFlipFlopStateNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/locals/LevelFlipFlopStateNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods.locals; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; + +public class LevelFlipFlopStateNode extends FlipFlopStateNode { + + private final int level; + private final FrameSlot frameSlot; + + public LevelFlipFlopStateNode(SourceSection sourceSection, int level, FrameSlot frameSlot) { + super(sourceSection); + this.level = level; + this.frameSlot = frameSlot; + } + + @Override + public boolean getState(VirtualFrame frame) { + final MaterializedFrame levelFrame = RubyArguments.getDeclarationFrame(frame, level); + + try { + return levelFrame.getBoolean(frameSlot); + } catch (FrameSlotTypeException e) { + throw new IllegalStateException(); + } + } + + @Override + public void setState(VirtualFrame frame, boolean state) { + final MaterializedFrame levelFrame = RubyArguments.getDeclarationFrame(frame, level); + levelFrame.setBoolean(frameSlot, state); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/locals/LocalFlipFlopStateNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/locals/LocalFlipFlopStateNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods.locals; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; + +public class LocalFlipFlopStateNode extends FlipFlopStateNode { + + private final FrameSlot frameSlot; + + public LocalFlipFlopStateNode(SourceSection sourceSection, FrameSlot frameSlot) { + super(sourceSection); + this.frameSlot = frameSlot; + } + + @Override + public boolean getState(VirtualFrame frame) { + try { + return frame.getBoolean(frameSlot); + } catch (FrameSlotTypeException e) { + throw new IllegalStateException(); + } + } + + @Override + public void setState(VirtualFrame frame, boolean state) { + frame.setBoolean(frameSlot, state); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/locals/ReadLevelVariableNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/locals/ReadLevelVariableNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods.locals; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +public abstract class ReadLevelVariableNode extends FrameSlotNode implements ReadNode { + + private final int varLevel; + + public ReadLevelVariableNode(RubyContext context, SourceSection sourceSection, FrameSlot slot, int level) { + super(context, sourceSection, slot); + this.varLevel = level; + } + + public ReadLevelVariableNode(ReadLevelVariableNode prev) { + this(prev.getContext(), prev.getSourceSection(), prev.frameSlot, prev.varLevel); + } + + @Specialization(rewriteOn = {FrameSlotTypeException.class}) + public boolean doBoolean(VirtualFrame frame) throws FrameSlotTypeException { + MaterializedFrame levelFrame = RubyArguments.getDeclarationFrame(frame, varLevel); + return getBoolean(levelFrame); + } + + @Specialization(rewriteOn = {FrameSlotTypeException.class}) + public int doFixnum(VirtualFrame frame) throws FrameSlotTypeException { + MaterializedFrame levelFrame = RubyArguments.getDeclarationFrame(frame, varLevel); + return getFixnum(levelFrame); + } + + @Specialization(rewriteOn = {FrameSlotTypeException.class}) + public double doFloat(VirtualFrame frame) throws FrameSlotTypeException { + MaterializedFrame levelFrame = RubyArguments.getDeclarationFrame(frame, varLevel); + return getFloat(levelFrame); + } + + @Specialization + public Object doObject(VirtualFrame frame) { + MaterializedFrame levelFrame = RubyArguments.getDeclarationFrame(frame, varLevel); + return getObject(levelFrame); + } + + public int getVarLevel() { + return varLevel; + } + + @Override + public RubyNode makeWriteNode(RubyNode rhs) { + return WriteLevelVariableNodeFactory.create(getContext(), getSourceSection(), frameSlot, varLevel, rhs); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/locals/ReadLocalVariableNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/locals/ReadLocalVariableNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods.locals; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +public abstract class ReadLocalVariableNode extends FrameSlotNode implements ReadNode { + + public ReadLocalVariableNode(RubyContext context, SourceSection sourceSection, FrameSlot slot) { + super(context, sourceSection, slot); + } + + public ReadLocalVariableNode(ReadLocalVariableNode prev) { + this(prev.getContext(), prev.getSourceSection(), prev.frameSlot); + } + + @Specialization(rewriteOn = {FrameSlotTypeException.class}) + public boolean doBoolean(VirtualFrame frame) throws FrameSlotTypeException { + return getBoolean(frame); + } + + @Specialization(rewriteOn = {FrameSlotTypeException.class}) + public int doFixnum(VirtualFrame frame) throws FrameSlotTypeException { + return getFixnum(frame); + } + + @Specialization(rewriteOn = {FrameSlotTypeException.class}) + public double doFloat(VirtualFrame frame) throws FrameSlotTypeException { + return getFloat(frame); + } + + @Specialization + public Object doObject(VirtualFrame frame) { + return getObject(frame); + } + + @Override + public RubyNode makeWriteNode(RubyNode rhs) { + return WriteLocalVariableNodeFactory.create(getContext(), getSourceSection(), frameSlot, rhs); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/locals/WriteLevelVariableNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/locals/WriteLevelVariableNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods.locals; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +@NodeChild(value = "rhs", type = RubyNode.class) +public abstract class WriteLevelVariableNode extends FrameSlotNode implements WriteNode { + + private final int varLevel; + + public WriteLevelVariableNode(RubyContext context, SourceSection sourceSection, FrameSlot frameSlot, int level) { + super(context, sourceSection, frameSlot); + this.varLevel = level; + } + + protected WriteLevelVariableNode(WriteLevelVariableNode prev) { + this(prev.getContext(), prev.getSourceSection(), prev.frameSlot, prev.varLevel); + } + + @Specialization(guards = "isBooleanKind") + public boolean doBoolean(VirtualFrame frame, boolean value) { + MaterializedFrame levelFrame = RubyArguments.getDeclarationFrame(frame, varLevel); + setBoolean(levelFrame, value); + return value; + } + + @Specialization(guards = "isFixnumKind") + public int doFixnum(VirtualFrame frame, int value) { + MaterializedFrame levelFrame = RubyArguments.getDeclarationFrame(frame, varLevel); + setFixnum(levelFrame, value); + return value; + } + + @Specialization(guards = "isFloatKind") + public double doFloat(VirtualFrame frame, double value) { + MaterializedFrame levelFrame = RubyArguments.getDeclarationFrame(frame, varLevel); + setFloat(levelFrame, value); + return value; + } + + @Specialization(guards = "isObjectKind") + public Object doObject(VirtualFrame frame, Object value) { + MaterializedFrame levelFrame = RubyArguments.getDeclarationFrame(frame, varLevel); + setObject(levelFrame, value); + return value; + } + + @Override + public RubyNode makeReadNode() { + return ReadLevelVariableNodeFactory.create(getContext(), getSourceSection(), frameSlot, varLevel); + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/locals/WriteLocalVariableNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/methods/locals/WriteLocalVariableNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.methods.locals; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +@NodeChild(value = "rhs", type = RubyNode.class) +public abstract class WriteLocalVariableNode extends FrameSlotNode implements WriteNode { + + public WriteLocalVariableNode(RubyContext context, SourceSection sourceSection, FrameSlot frameSlot) { + super(context, sourceSection, frameSlot); + } + + protected WriteLocalVariableNode(WriteLocalVariableNode prev) { + this(prev.getContext(), prev.getSourceSection(), prev.frameSlot); + } + + @Specialization(guards = "isBooleanKind") + public boolean doFixnum(VirtualFrame frame, boolean value) { + setBoolean(frame, value); + return value; + } + + @Specialization(guards = "isFixnumKind") + public int doFixnum(VirtualFrame frame, int value) { + setFixnum(frame, value); + return value; + } + + @Specialization(guards = "isFloatKind") + public double doFloat(VirtualFrame frame, double value) { + setFloat(frame, value); + return value; + } + + @Specialization(guards = "isObjectKind") + public Object doObject(VirtualFrame frame, Object value) { + setObject(frame, value); + return value; + } + + @Override + public RubyNode makeReadNode() { + return ReadLocalVariableNodeFactory.create(getContext(), getSourceSection(), frameSlot); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/ClassNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/ClassNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Reads the class of an object. + */ +@NodeInfo(shortName = "class") +public class ClassNode extends RubyNode { + + @Child protected RubyNode child; + + public ClassNode(RubyContext context, SourceSection sourceSection, RubyNode child) { + super(context, sourceSection); + this.child = adoptChild(child); + } + + @Override + public Object execute(VirtualFrame frame) { + return ((RubyBasicObject) child.execute(frame)).getRubyClass(); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/DefineOrGetClassNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/DefineOrGetClassNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * Define a new class, or get the existing one of the same name. + */ +public class DefineOrGetClassNode extends RubyNode { + + private final String name; + @Child protected RubyNode moduleDefinedIn; + @Child protected RubyNode superClass; + + public DefineOrGetClassNode(RubyContext context, SourceSection sourceSection, String name, RubyNode moduleDefinedIn, RubyNode superClass) { + super(context, sourceSection); + this.name = name; + this.moduleDefinedIn = adoptChild(moduleDefinedIn); + this.superClass = adoptChild(superClass); + } + + @Override + public Object execute(VirtualFrame frame) { + CompilerAsserts.neverPartOfCompilation(); + + final RubyContext context = getContext(); + + final RubyModule moduleDefinedInObject = (RubyModule) moduleDefinedIn.execute(frame); + + // Look for a current definition of the class, or create a new one + + final Object constantValue = moduleDefinedInObject.lookupConstant(name); + + RubyClass definingClass; + + if (constantValue == null) { + final Object self = frame.getArguments(RubyArguments.class).getSelf(); + + RubyModule parentModule; + + if (self instanceof RubyModule) { + parentModule = (RubyModule) self; + } else { + // Because it's top level, and so self is the magic main object + parentModule = null; + } + + final RubyClass superClassObject = (RubyClass) superClass.execute(frame); + + if (superClassObject instanceof RubyException.RubyExceptionClass) { + definingClass = new RubyException.RubyExceptionClass(superClassObject, name); + } else { + definingClass = new RubyClass(parentModule, superClassObject, name); + } + + moduleDefinedInObject.setConstant(name, definingClass); + moduleDefinedInObject.getSingletonClass().setConstant(name, definingClass); + + definingClass.getRubyClass().include(moduleDefinedInObject); + } else { + if (constantValue instanceof RubyClass) { + definingClass = (RubyClass) constantValue; + } else { + throw new RaiseException(context.getCoreLibrary().typeErrorIsNotA(constantValue.toString(), "class")); + } + } + + return definingClass; + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/DefineOrGetModuleNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/DefineOrGetModuleNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * Define a new module, or get the existing one of the same name. + */ +public class DefineOrGetModuleNode extends RubyNode { + + private final String name; + @Child protected RubyNode moduleDefinedIn; + + public DefineOrGetModuleNode(RubyContext context, SourceSection sourceSection, String name, RubyNode moduleDefinedIn) { + super(context, sourceSection); + this.name = name; + this.moduleDefinedIn = adoptChild(moduleDefinedIn); + } + + @Override + public Object execute(VirtualFrame frame) { + CompilerAsserts.neverPartOfCompilation(); + + final RubyContext context = getContext(); + + final RubyModule moduleDefinedInObject = (RubyModule) moduleDefinedIn.execute(frame); + + // Look for a current definition of the module, or create a new one + + final Object constantValue = moduleDefinedInObject.lookupConstant(name); + + RubyModule definingModule; + + if (constantValue == null) { + final Object self = frame.getArguments(RubyArguments.class).getSelf(); + + RubyModule parentModule; + + if (self instanceof RubyModule) { + parentModule = (RubyModule) self; + } else { + // Because it's top level, and so self is the magic main object + parentModule = null; + } + + definingModule = new RubyModule(context.getCoreLibrary().getModuleClass(), parentModule, name); + moduleDefinedInObject.setConstant(name, definingModule); + moduleDefinedInObject.getSingletonClass().setConstant(name, definingModule); + } else { + if (constantValue instanceof RubyModule) { + definingModule = (RubyModule) constantValue; + } else { + throw new RaiseException(context.getCoreLibrary().typeErrorIsNotA(constantValue.toString(), "module")); + } + } + + return definingModule; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/OpenModuleNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/OpenModuleNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.nodes.methods.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * Open a module and execute a method in it - probably to define new methods. + */ +public class OpenModuleNode extends RubyNode { + + @Child protected RubyNode definingModule; + @Child protected MethodDefinitionNode definitionMethod; + + public OpenModuleNode(RubyContext context, SourceSection sourceSection, RubyNode definingModule, MethodDefinitionNode definitionMethod) { + super(context, sourceSection); + this.definingModule = adoptChild(definingModule); + this.definitionMethod = adoptChild(definitionMethod); + } + + @Override + public Object execute(VirtualFrame frame) { + CompilerAsserts.neverPartOfCompilation(); + + // Call the definition method with the module as self - there's no return value + + final RubyModule module = (RubyModule) definingModule.execute(frame); + definitionMethod.executeMethod(frame).call(frame.pack(), module, null); + + return NilPlaceholder.INSTANCE; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/ReadClassVariableNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/ReadClassVariableNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +@NodeInfo(shortName = "read-class-variable") +public class ReadClassVariableNode extends RubyNode { + + protected final String name; + @Child protected RubyNode module; + + public ReadClassVariableNode(RubyContext context, SourceSection sourceSection, String name, RubyNode module) { + super(context, sourceSection); + this.name = name; + this.module = adoptChild(module); + } + + @Override + public Object execute(VirtualFrame frame) { + final RubyObject object = (RubyObject) module.execute(frame); + + RubyModule moduleObject; + + // TODO(CS): this cannot be right + + if (object instanceof RubyModule) { + moduleObject = (RubyModule) object; + } else { + moduleObject = object.getRubyClass(); + } + + final Object value = moduleObject.lookupClassVariable(name); + + if (value == null) { + // TODO(CS): is this right? + return NilPlaceholder.INSTANCE; + } + + return value; + } + + @Override + public Object isDefined(VirtualFrame frame) { + final RubyContext context = getContext(); + + final RubyObject object = (RubyObject) module.execute(frame); + + RubyModule moduleObject; + + if (object instanceof RubyModule) { + moduleObject = (RubyModule) object; + } else { + moduleObject = object.getRubyClass(); + } + + final Object value = moduleObject.lookupClassVariable(name); + + if (value == null) { + return NilPlaceholder.INSTANCE; + } else { + return context.makeString("class variable"); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/SelfNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/SelfNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +@NodeInfo(shortName = "self") +public class SelfNode extends RubyNode { + + public SelfNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + @Override + public Object execute(VirtualFrame frame) { + final Object self = frame.getArguments(RubyArguments.class).getSelf(); + assert RubyContext.shouldObjectBeVisible(self); + return self; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/SingletonClassNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/SingletonClassNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects; + +import java.math.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Reads the singleton (meta, eigen) class of an object. + */ +@NodeInfo(shortName = "singleton") +public class SingletonClassNode extends RubyNode { + + @Child protected RubyNode child; + + public SingletonClassNode(RubyContext context, SourceSection sourceSection, RubyNode child) { + super(context, sourceSection); + this.child = adoptChild(child); + } + + @Override + public Object execute(VirtualFrame frame) { + final Object childResult = child.execute(frame); + + final RubyContext context = getContext(); + + if (childResult instanceof NilPlaceholder) { + return context.getCoreLibrary().getNilClass(); + } else if (childResult instanceof BigInteger) { + // TODO(CS): this is problematic - do Bignums have singletons or not? + return context.getCoreLibrary().box(childResult).getSingletonClass(); + } else { + return ((RubyBasicObject) childResult).getSingletonClass(); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/WriteClassVariableNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/WriteClassVariableNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +@NodeInfo(shortName = "write-class-variable") +public class WriteClassVariableNode extends RubyNode { + + private final String name; + @Child protected RubyNode module; + @Child protected RubyNode rhs; + + public WriteClassVariableNode(RubyContext context, SourceSection sourceSection, String name, RubyNode module, RubyNode rhs) { + super(context, sourceSection); + this.name = name; + this.module = adoptChild(module); + this.rhs = adoptChild(rhs); + } + + @Override + public Object execute(VirtualFrame frame) { + // TODO(CS): can module ever not evaluate to a RubyModule? + + final RubyModule moduleObject = (RubyModule) module.execute(frame); + + final Object rhsValue = rhs.execute(frame); + + moduleObject.setClassVariable(name, rhsValue); + + return rhsValue; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/ReadFixnumInstanceVariableNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/ReadFixnumInstanceVariableNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects.instancevariables; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +@NodeInfo(shortName = "@Fixnum") +public class ReadFixnumInstanceVariableNode extends ReadSpecializedInstanceVariableNode { + + private final FixnumStorageLocation storageLocation; + + public ReadFixnumInstanceVariableNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver, ObjectLayout objectLayout, FixnumStorageLocation storageLocation) { + super(context, sourceSection, name, receiver, objectLayout); + this.storageLocation = storageLocation; + } + + @Override + public int executeFixnum(VirtualFrame frame) throws UnexpectedResultException { + final RubyBasicObject receiverObject = (RubyBasicObject) receiver.execute(frame); + + final ObjectLayout receiverLayout = receiverObject.getObjectLayout(); + + final boolean condition = receiverLayout == objectLayout; + + if (condition) { + assert receiverLayout != null; + return storageLocation.readFixnum(receiverObject, condition); + } else { + CompilerDirectives.transferToInterpreter(); + replace(respecialize(receiverObject)); + throw new UnexpectedResultException(receiverObject.getInstanceVariable(name)); + } + } + + @Override + public Object execute(VirtualFrame frame) { + try { + return executeFixnum(frame); + } catch (UnexpectedResultException e) { + return e.getResult(); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/ReadFloatInstanceVariableNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/ReadFloatInstanceVariableNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects.instancevariables; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +@NodeInfo(shortName = "@Float") +public class ReadFloatInstanceVariableNode extends ReadSpecializedInstanceVariableNode { + + private final FloatStorageLocation storageLocation; + + public ReadFloatInstanceVariableNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver, ObjectLayout objectLayout, FloatStorageLocation storageLocation) { + super(context, sourceSection, name, receiver, objectLayout); + this.storageLocation = storageLocation; + } + + @Override + public double executeFloat(VirtualFrame frame) throws UnexpectedResultException { + final RubyBasicObject receiverObject = (RubyBasicObject) receiver.execute(frame); + + final ObjectLayout receiverLayout = receiverObject.getObjectLayout(); + + final boolean condition = receiverLayout == objectLayout; + + if (condition) { + assert receiverLayout != null; + return storageLocation.readFloat(receiverObject, condition); + } else { + CompilerDirectives.transferToInterpreter(); + replace(respecialize(receiverObject)); + throw new UnexpectedResultException(receiverObject.getInstanceVariable(name)); + } + } + + @Override + public Object execute(VirtualFrame frame) { + try { + return executeFloat(frame); + } catch (UnexpectedResultException e) { + return e.getResult(); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/ReadInstanceVariableNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/ReadInstanceVariableNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects.instancevariables; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +public abstract class ReadInstanceVariableNode extends RubyNode implements ReadNode { + + protected final String name; + @Child protected RubyNode receiver; + + public ReadInstanceVariableNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver) { + super(context, sourceSection); + this.name = name; + this.receiver = adoptChild(receiver); + } + + public ReadInstanceVariableNode respecialize(RubyBasicObject receiverObject) { + final StorageLocation storageLocation = receiverObject.getUpdatedObjectLayout().findStorageLocation(name); + + if (storageLocation == null) { + return new ReadMissingInstanceVariableNode(getSourceSection(), name, receiver, receiverObject.getObjectLayout(), getContext()); + } + + if (storageLocation instanceof FixnumStorageLocation) { + return new ReadFixnumInstanceVariableNode(getContext(), getSourceSection(), name, receiver, storageLocation.getObjectLayout(), (FixnumStorageLocation) storageLocation); + } else if (storageLocation instanceof FloatStorageLocation) { + return new ReadFloatInstanceVariableNode(getContext(), getSourceSection(), name, receiver, storageLocation.getObjectLayout(), (FloatStorageLocation) storageLocation); + } else { + return new ReadObjectInstanceVariableNode(getContext(), getSourceSection(), name, receiver, storageLocation.getObjectLayout(), (ObjectStorageLocation) storageLocation); + } + } + + public WriteInstanceVariableNode makeWriteNode(RubyNode rhs) { + return new UninitializedWriteInstanceVariableNode(getContext(), getEncapsulatingSourceSection(), name, (RubyNode) receiver.copy(), rhs); + } + + public String getName() { + return name; + } + + public RubyNode getReceiver() { + return receiver; + } + + @Override + public Object isDefined(VirtualFrame frame) { + final RubyContext context = getContext(); + + try { + final Object receiverObject = receiver.execute(frame); + final RubyBasicObject receiverRubyObject = context.getCoreLibrary().box(receiverObject); + + final ObjectLayout layout = receiverRubyObject.getObjectLayout(); + final StorageLocation storageLocation = layout.findStorageLocation(name); + + if (storageLocation.isSet(receiverRubyObject)) { + return context.makeString("instance-variable"); + } else { + return NilPlaceholder.INSTANCE; + } + } catch (Exception e) { + return NilPlaceholder.INSTANCE; + } + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/ReadMissingInstanceVariableNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/ReadMissingInstanceVariableNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects.instancevariables; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +@NodeInfo(shortName = "@missing") +public class ReadMissingInstanceVariableNode extends ReadSpecializedInstanceVariableNode { + + public ReadMissingInstanceVariableNode(SourceSection sourceSection, String name, RubyNode receiver, ObjectLayout objectLayout, RubyContext context) { + super(context, sourceSection, name, receiver, objectLayout); + } + + @Override + public Object execute(VirtualFrame frame) { + final RubyBasicObject receiverObject = (RubyBasicObject) receiver.execute(frame); + + if (!receiverObject.getObjectLayout().contains(objectLayout)) { + CompilerDirectives.transferToInterpreter(); + replace(respecialize(receiverObject)); + return receiverObject.getInstanceVariable(name); + } + + return NilPlaceholder.INSTANCE; + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/ReadObjectInstanceVariableNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/ReadObjectInstanceVariableNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects.instancevariables; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +@NodeInfo(shortName = "@Object") +public class ReadObjectInstanceVariableNode extends ReadSpecializedInstanceVariableNode { + + private final ObjectStorageLocation storageLocation; + + public ReadObjectInstanceVariableNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver, ObjectLayout objectLayout, ObjectStorageLocation storageLocation) { + super(context, sourceSection, name, receiver, objectLayout); + this.storageLocation = storageLocation; + } + + @Override + public Object execute(VirtualFrame frame) { + final RubyBasicObject receiverObject = (RubyBasicObject) receiver.execute(frame); + + final ObjectLayout receiverLayout = receiverObject.getObjectLayout(); + + final boolean condition = receiverLayout == objectLayout; + + if (condition) { + assert receiverLayout != null; + return storageLocation.read(receiverObject, condition); + } else { + CompilerDirectives.transferToInterpreter(); + replace(respecialize(receiverObject)); + return receiverObject.getInstanceVariable(name); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/ReadSpecializedInstanceVariableNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/ReadSpecializedInstanceVariableNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects.instancevariables; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +public abstract class ReadSpecializedInstanceVariableNode extends ReadInstanceVariableNode { + + protected final ObjectLayout objectLayout; + + public ReadSpecializedInstanceVariableNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver, ObjectLayout objectLayout) { + super(context, sourceSection, name, receiver); + this.objectLayout = objectLayout; + } + + protected void respecialize() { + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/UninitializedReadInstanceVariableNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/UninitializedReadInstanceVariableNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects.instancevariables; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +@NodeInfo(shortName = "@uninit") +public class UninitializedReadInstanceVariableNode extends ReadInstanceVariableNode { + + public UninitializedReadInstanceVariableNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver) { + super(context, sourceSection, name, receiver); + } + + @Override + public Object execute(VirtualFrame frame) { + CompilerDirectives.transferToInterpreter(); + final RubyBasicObject receiverObject = (RubyBasicObject) receiver.execute(frame); + replace(respecialize(receiverObject)); + return receiverObject.getInstanceVariable(name); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/UninitializedWriteInstanceVariableNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/UninitializedWriteInstanceVariableNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects.instancevariables; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +@NodeInfo(shortName = "@uninit=") +public class UninitializedWriteInstanceVariableNode extends WriteInstanceVariableNode { + + public UninitializedWriteInstanceVariableNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver, RubyNode rhs) { + super(context, sourceSection, name, receiver, rhs); + } + + @Override + public Object execute(VirtualFrame frame) { + CompilerDirectives.transferToInterpreter(); + final RubyBasicObject receiverObject = (RubyBasicObject) receiver.execute(frame); + final Object value = rhs.execute(frame); + receiverObject.setInstanceVariable(name, value); + replace(respecialize(receiverObject)); + return value; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/WriteFixnumInstanceVariableNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/WriteFixnumInstanceVariableNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects.instancevariables; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +@NodeInfo(shortName = "@Fixnum=") +public class WriteFixnumInstanceVariableNode extends WriteSpecializedInstanceVariableNode { + + private final FixnumStorageLocation storageLocation; + + public WriteFixnumInstanceVariableNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver, RubyNode rhs, ObjectLayout objectLayout, + FixnumStorageLocation storageLocation) { + super(context, sourceSection, name, receiver, rhs, objectLayout); + this.storageLocation = storageLocation; + } + + @Override + public int executeFixnum(VirtualFrame frame) throws UnexpectedResultException { + final RubyBasicObject receiverObject = (RubyBasicObject) receiver.execute(frame); + + int value; + + try { + value = rhs.executeFixnum(frame); + } catch (UnexpectedResultException e) { + receiverObject.setInstanceVariable(name, e.getResult()); + replace(respecialize(receiverObject)); + throw e; + } + + final ObjectLayout receiverLayout = receiverObject.getObjectLayout(); + + if (receiverLayout != objectLayout) { + CompilerDirectives.transferToInterpreter(); + receiverObject.setInstanceVariable(name, value); + replace(respecialize(receiverObject)); + return value; + } + + assert receiverLayout != null; + + storageLocation.writeFixnum(receiverObject, value); + return value; + } + + @Override + public Object execute(VirtualFrame frame) { + try { + return executeFixnum(frame); + } catch (UnexpectedResultException e) { + return e.getResult(); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/WriteFloatInstanceVariableNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/WriteFloatInstanceVariableNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects.instancevariables; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +@NodeInfo(shortName = "@Float=") +public class WriteFloatInstanceVariableNode extends WriteSpecializedInstanceVariableNode { + + private final FloatStorageLocation storageLocation; + + public WriteFloatInstanceVariableNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver, RubyNode rhs, ObjectLayout objectLayout, + FloatStorageLocation storageLocation) { + super(context, sourceSection, name, receiver, rhs, objectLayout); + this.storageLocation = storageLocation; + } + + @Override + public double executeFloat(VirtualFrame frame) throws UnexpectedResultException { + final RubyBasicObject receiverObject = (RubyBasicObject) receiver.execute(frame); + + double value; + + try { + value = rhs.executeFloat(frame); + } catch (UnexpectedResultException e) { + receiverObject.setInstanceVariable(name, e.getResult()); + replace(respecialize(receiverObject)); + throw e; + } + + final ObjectLayout receiverLayout = receiverObject.getObjectLayout(); + + if (receiverLayout != objectLayout) { + CompilerDirectives.transferToInterpreter(); + receiverObject.setInstanceVariable(name, value); + replace(respecialize(receiverObject)); + return value; + } + + assert receiverLayout != null; + + storageLocation.writeFloat(receiverObject, value); + return value; + } + + @Override + public Object execute(VirtualFrame frame) { + try { + return executeFloat(frame); + } catch (UnexpectedResultException e) { + return e.getResult(); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/WriteInstanceVariableNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/WriteInstanceVariableNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects.instancevariables; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +public abstract class WriteInstanceVariableNode extends RubyNode implements WriteNode { + + protected final String name; + @Child protected RubyNode receiver; + @Child protected RubyNode rhs; + + public WriteInstanceVariableNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver, RubyNode rhs) { + super(context, sourceSection); + this.name = name; + this.receiver = adoptChild(receiver); + this.rhs = adoptChild(rhs); + } + + public WriteInstanceVariableNode respecialize(RubyBasicObject receiverObject) { + StorageLocation storageLocation = receiverObject.getObjectLayout().findStorageLocation(name); + + if (storageLocation == null) { + throw new RuntimeException("Storage location should be found at this point"); + } + + if (storageLocation instanceof FixnumStorageLocation) { + return new WriteFixnumInstanceVariableNode(getContext(), getSourceSection(), name, receiver, rhs, storageLocation.getObjectLayout(), (FixnumStorageLocation) storageLocation); + } else if (storageLocation instanceof FloatStorageLocation) { + return new WriteFloatInstanceVariableNode(getContext(), getSourceSection(), name, receiver, rhs, storageLocation.getObjectLayout(), (FloatStorageLocation) storageLocation); + } else { + return new WriteObjectInstanceVariableNode(getContext(), getSourceSection(), name, receiver, rhs, storageLocation.getObjectLayout(), (ObjectStorageLocation) storageLocation); + } + } + + @Override + public ReadInstanceVariableNode makeReadNode() { + return new UninitializedReadInstanceVariableNode(getContext(), getEncapsulatingSourceSection(), name, (RubyNode) receiver.copy()); + } + + public String getName() { + return name; + } + + public RubyNode getReceiver() { + return receiver; + } + + public RubyNode getRHS() { + return rhs; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/WriteObjectInstanceVariableNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/WriteObjectInstanceVariableNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects.instancevariables; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +@NodeInfo(shortName = "@Object=") +public class WriteObjectInstanceVariableNode extends WriteSpecializedInstanceVariableNode { + + private final ObjectStorageLocation storageLocation; + + public WriteObjectInstanceVariableNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver, RubyNode rhs, ObjectLayout objectLayout, + ObjectStorageLocation storageLocation) { + super(context, sourceSection, name, receiver, rhs, objectLayout); + this.storageLocation = storageLocation; + } + + @Override + public Object execute(VirtualFrame frame) { + final RubyBasicObject receiverObject = (RubyBasicObject) receiver.execute(frame); + final Object value = rhs.execute(frame); + + final ObjectLayout receiverLayout = receiverObject.getObjectLayout(); + + if (receiverLayout != objectLayout) { + CompilerDirectives.transferToInterpreter(); + receiverObject.setInstanceVariable(name, value); + replace(respecialize(receiverObject)); + return value; + } + + assert receiverLayout != null; + + storageLocation.write(receiverObject, value); + return value; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/WriteSpecializedInstanceVariableNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/objects/instancevariables/WriteSpecializedInstanceVariableNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.objects.instancevariables; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +public abstract class WriteSpecializedInstanceVariableNode extends WriteInstanceVariableNode { + + protected final ObjectLayout objectLayout; + + public WriteSpecializedInstanceVariableNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver, RubyNode rhs, ObjectLayout objectLayout) { + super(context, sourceSection, name, receiver, rhs); + this.objectLayout = objectLayout; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/yield/GeneralYieldDispatchNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/yield/GeneralYieldDispatchNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.yield; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * A yield dispatch node that just calls {@link RubyProc#call} as normal. + */ +public class GeneralYieldDispatchNode extends YieldDispatchNode { + + public GeneralYieldDispatchNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + @Override + public Object dispatch(VirtualFrame frame, RubyProc block, Object[] argumentsObjects) { + return block.call(frame.pack(), argumentsObjects); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/yield/InlinedYieldDispatchNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/yield/InlinedYieldDispatchNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.yield; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * Dispatch to a known method which has been inlined. + */ +public class InlinedYieldDispatchNode extends YieldDispatchNode { + + private final RubyRootNode pristineRootNode; + + private final FrameDescriptor frameDescriptor; + private final RubyRootNode rootNode; + + public InlinedYieldDispatchNode(RubyContext context, SourceSection sourceSection, InlinableMethodImplementation method) { + super(context, sourceSection); + pristineRootNode = method.getPristineRootNode(); + frameDescriptor = method.getFrameDescriptor(); + rootNode = method.getCloneOfPristineRootNode(); + } + + @Override + public Object dispatch(VirtualFrame frame, RubyProc block, Object[] argumentsObjects) { + /* + * We're inlining based on the root node used, checking that root node still matches, and + * then taking the materialized frame from the block we actually got. We can't look for + * RubyMethod or RubyProc, because they're allocated for each call passing a block. + */ + + if (!(block.getMethod().getImplementation() instanceof InlinableMethodImplementation) || + ((InlinableMethodImplementation) block.getMethod().getImplementation()).getPristineRootNode() != pristineRootNode) { + CompilerDirectives.transferToInterpreter(); + + // TODO(CS): at the moment we just go back to uninit, which may cause loops + + final UninitializedYieldDispatchNode dispatch = new UninitializedYieldDispatchNode(getContext(), getSourceSection()); + replace(dispatch); + return dispatch.dispatch(frame, block, argumentsObjects); + } + + final InlinableMethodImplementation implementation = (InlinableMethodImplementation) block.getMethod().getImplementation(); + + final RubyArguments arguments = new RubyArguments(implementation.getDeclarationFrame(), block.getSelf(), block.getBlock(), argumentsObjects); + final VirtualFrame inlinedFrame = Truffle.getRuntime().createVirtualFrame(frame.pack(), arguments, frameDescriptor); + return rootNode.execute(inlinedFrame); + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/yield/UninitializedYieldDispatchNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/yield/UninitializedYieldDispatchNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.yield; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.nodes.call.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +/** + * An uninitialized node in the yield dispatch chain. + */ +public class UninitializedYieldDispatchNode extends YieldDispatchNode { + + public UninitializedYieldDispatchNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + @Override + public Object dispatch(VirtualFrame frame, RubyProc block, Object[] argumentsObjects) { + CompilerDirectives.transferToInterpreter(); + + final MethodImplementation implementation = block.getMethod().getImplementation(); + + if (implementation instanceof InlinableMethodImplementation && InlineHeuristic.shouldInlineYield((InlinableMethodImplementation) implementation)) { + final InlinedYieldDispatchNode dispatch = new InlinedYieldDispatchNode(getContext(), getSourceSection(), (InlinableMethodImplementation) implementation); + replace(dispatch); + return dispatch.dispatch(frame, block, argumentsObjects); + } else { + final GeneralYieldDispatchNode dispatch = new GeneralYieldDispatchNode(getContext(), getSourceSection()); + replace(dispatch); + return dispatch.dispatch(frame, block, argumentsObjects); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/yield/YieldDispatchNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/yield/YieldDispatchNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.yield; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * A node in the yield dispatch chain. + */ +public abstract class YieldDispatchNode extends Node { + + private final RubyContext context; + + public YieldDispatchNode(RubyContext context, SourceSection sourceSection) { + super(sourceSection); + + assert context != null; + assert sourceSection != null; + + this.context = context; + } + + public abstract Object dispatch(VirtualFrame frame, RubyProc block, Object[] argumentsObjects); + + public RubyContext getContext() { + return context; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/yield/YieldNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.nodes/src/com/oracle/truffle/ruby/nodes/yield/YieldNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.nodes.yield; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * Yield to the current block. + */ +@NodeInfo(shortName = "yield") +public class YieldNode extends RubyNode { + + @Children protected final RubyNode[] arguments; + @Child protected YieldDispatchNode dispatch; + + public YieldNode(RubyContext context, SourceSection sourceSection, RubyNode[] arguments) { + super(context, sourceSection); + this.arguments = adoptChildren(arguments); + dispatch = adoptChild(new UninitializedYieldDispatchNode(getContext(), getSourceSection())); + } + + @ExplodeLoop + @Override + public final Object execute(VirtualFrame frame) { + final Object[] argumentsObjects = new Object[arguments.length]; + + for (int i = 0; i < arguments.length; i++) { + argumentsObjects[i] = arguments[i].execute(frame); + } + + final RubyProc block = frame.getArguments(RubyArguments.class).getBlock(); + + if (block == null) { + CompilerDirectives.transferToInterpreter(); + // TODO(CS): convert to the proper Ruby exception + throw new RuntimeException("No block to yield to"); + } + + return dispatch.dispatch(frame, block, argumentsObjects); + } + + @Override + public Object isDefined(VirtualFrame frame) { + final RubyArguments args = frame.getArguments(RubyArguments.class); + + if (args.getBlock() == null) { + return NilPlaceholder.INSTANCE; + } else { + return getContext().makeString("yield"); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/DeadNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/DeadNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.parser; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * Dead nodes are removed wherever they are found during translation. They fill in for some missing + * nodes when we're processing the AST. + */ +public class DeadNode extends RubyNode { + + public DeadNode(RubyContext context, SourceSection sourceSection) { + super(context, sourceSection); + } + + @Override + public Object execute(VirtualFrame frame) { + throw new UnsupportedOperationException("Dead nodes should have been pruned before execution starts"); + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/JRubyParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/JRubyParser.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.parser; + +import java.io.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.nodes.control.*; +import com.oracle.truffle.ruby.nodes.literal.*; +import com.oracle.truffle.ruby.nodes.methods.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.debug.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +public class JRubyParser implements RubyParser { + + private long nextReturnID = 0; + + @Override + public RubyParserResult parse(RubyContext context, Source source, ParserContext parserContext, MaterializedFrame parentFrame) { + // Set up the JRuby parser + + final org.jrubyparser.Parser parser = new org.jrubyparser.Parser(); + + org.jrubyparser.CompatVersion parserVersion = null; + + switch (context.getConfiguration().getRubyVersion()) { + case RUBY_18: + parserVersion = org.jrubyparser.CompatVersion.RUBY1_8; + break; + case RUBY_19: + parserVersion = org.jrubyparser.CompatVersion.RUBY1_9; + break; + case RUBY_20: + parserVersion = org.jrubyparser.CompatVersion.RUBY2_0; + break; + case RUBY_21: + parserVersion = org.jrubyparser.CompatVersion.RUBY2_0; + break; + } + + // TODO(cs) should this get a new unique method identifier or not? + final TranslatorEnvironment environment = new TranslatorEnvironment(context, environmentForFrame(context, parentFrame), this, allocateReturnID(), true, true, new UniqueMethodIdentifier()); + + // All parsing contexts have a visibility slot at their top level + + environment.addMethodDeclarationSlots(); + + final org.jrubyparser.LocalStaticScope staticScope = new org.jrubyparser.LocalStaticScope(null); + + if (parentFrame != null) { + /* + * Note that jruby-parser will be mistaken about how deep the existing variables are, + * but that doesn't matter as we look them up ourselves after being told their in some + * parent scope. + */ + + MaterializedFrame frame = parentFrame; + + while (frame != null) { + for (FrameSlot slot : frame.getFrameDescriptor().getSlots()) { + if (slot.getIdentifier() instanceof String) { + final String name = (String) slot.getIdentifier(); + if (staticScope.exists(name) == -1) { + staticScope.assign(null, name, null); + } + } + } + + frame = frame.getArguments(RubyArguments.class).getDeclarationFrame(); + } + } + + final org.jrubyparser.parser.ParserConfiguration parserConfiguration = new org.jrubyparser.parser.ParserConfiguration(0, parserVersion, staticScope); + + // Parse to the JRuby AST + + org.jrubyparser.ast.RootNode node; + + try { + node = (org.jrubyparser.ast.RootNode) parser.parse(source.getName(), new StringReader(source.getCode()), parserConfiguration); + } catch (UnsupportedOperationException | org.jrubyparser.lexer.SyntaxException e) { + String message = e.getMessage(); + + if (message == null) { + message = "(no message)"; + } + + throw new RaiseException(new RubyException(context.getCoreLibrary().getSyntaxErrorClass(), message)); + } + + if (context.getConfiguration().getPrintParseTree()) { + System.err.println(node); + } + + // Translate to Ruby Truffle nodes + + final Translator translator; + + if (parserContext == RubyParser.ParserContext.MODULE) { + translator = new ModuleTranslator(context, null, environment, source); + } else { + translator = new Translator(context, null, environment, source); + } + + RubyNode truffleNode; + + final RubyDebugManager debugManager = context.getDebugManager(); + try { + if (debugManager != null) { + debugManager.notifyStartLoading(source); + } + + if (node.getBody() == null) { + truffleNode = new NilNode(context, null); + } else { + truffleNode = (RubyNode) node.getBody().accept(translator); + } + + // Load flip-flop states + + if (environment.getFlipFlopStates().size() > 0) { + truffleNode = new SequenceNode(context, truffleNode.getSourceSection(), translator.initFlipFlopStates(truffleNode.getSourceSection()), truffleNode); + } + + // Catch next + + truffleNode = new CatchNextNode(context, truffleNode.getSourceSection(), truffleNode); + + // Catch return + + truffleNode = new CatchReturnAsErrorNode(context, truffleNode.getSourceSection(), truffleNode); + + // Shell result + + if (parserContext == RubyParser.ParserContext.SHELL) { + truffleNode = new ShellResultNode(context, truffleNode.getSourceSection(), truffleNode); + } + + // Root Node + + String indicativeName; + + switch (parserContext) { + case TOP_LEVEL: + indicativeName = "(main)"; + break; + case SHELL: + indicativeName = "(shell)"; + break; + case MODULE: + indicativeName = "(module)"; + break; + default: + throw new UnsupportedOperationException(); + } + + final RootNode root = new RubyRootNode(truffleNode.getSourceSection(), indicativeName, truffleNode); + + // Return the root and the frame descriptor + + return new RubyParserResult(root, environment.getFrameDescriptor()); + } finally { + if (debugManager != null) { + debugManager.notifyFinishedLoading(source); + } + } + } + + public long allocateReturnID() { + if (nextReturnID == Long.MAX_VALUE) { + throw new RuntimeException("Return IDs exhausted"); + } + + final long allocated = nextReturnID; + nextReturnID++; + return allocated; + } + + private TranslatorEnvironment environmentForFrame(RubyContext context, MaterializedFrame frame) { + if (frame == null) { + return null; + } else { + final MaterializedFrame parent = frame.getArguments(RubyArguments.class).getDeclarationFrame(); + return new TranslatorEnvironment(context, environmentForFrame(context, parent), frame.getFrameDescriptor(), this, allocateReturnID(), true, true, new UniqueMethodIdentifier()); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/MethodTranslator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/MethodTranslator.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.parser; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.nodes.call.*; +import com.oracle.truffle.ruby.nodes.control.*; +import com.oracle.truffle.ruby.nodes.literal.*; +import com.oracle.truffle.ruby.nodes.methods.*; +import com.oracle.truffle.ruby.nodes.methods.arguments.*; +import com.oracle.truffle.ruby.nodes.methods.locals.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +class MethodTranslator extends Translator { + + private boolean isBlock; + + public MethodTranslator(RubyContext context, Translator parent, TranslatorEnvironment environment, boolean isBlock, Source source) { + super(context, parent, environment, source); + this.isBlock = isBlock; + } + + public MethodDefinitionNode compileFunctionNode(SourceSection sourceSection, String methodName, org.jrubyparser.ast.ArgsNode argsNode, org.jrubyparser.ast.Node bodyNode) { + environment.setMethodName(methodName); + + final Arity arity = findParameters(argsNode); + + RubyNode body; + + if (bodyNode != null) { + body = (RubyNode) bodyNode.accept(this); + } else { + body = new NilNode(context, sourceSection); + } + + body = loadArgumentsIntoLocals(arity, body); + + if (environment.getFlipFlopStates().size() > 0) { + body = new SequenceNode(context, sourceSection, initFlipFlopStates(sourceSection), body); + } + + if (isBlock) { + body = new CatchNextNode(context, sourceSection, body); + } else { + body = new CatchReturnNode(context, sourceSection, body, environment.getReturnID()); + body = new CatchNextNode(context, sourceSection, body); + } + + final RubyRootNode pristineRootNode = new RubyRootNode(sourceSection, methodName, body); + + final CallTarget callTarget = Truffle.getRuntime().createCallTarget(NodeUtil.cloneNode(pristineRootNode), environment.getFrameDescriptor()); + + if (isBlock) { + return new BlockDefinitionNode(context, sourceSection, methodName, environment.getUniqueMethodIdentifier(), environment.getFrameDescriptor(), environment.needsDeclarationFrame(), + pristineRootNode, callTarget); + } else { + return new MethodDefinitionNode(context, sourceSection, methodName, environment.getUniqueMethodIdentifier(), environment.getFrameDescriptor(), environment.needsDeclarationFrame(), + pristineRootNode, callTarget); + } + } + + private RubyNode loadArgumentsIntoLocals(Arity arity, RubyNode body) { + final SourceSection sourceSection = body.getEncapsulatingSourceSection(); + + final List loadIndividualArgumentsNodes = new ArrayList<>(); + + if (!isBlock) { + loadIndividualArgumentsNodes.add(new CheckArityNode(context, sourceSection, arity)); + } + + final int preCount = environment.getPreParameters().size(); + final int postCount = environment.getPostParameters().size(); + + for (int n = 0; n < environment.getPreParameters().size(); n++) { + final FrameSlot param = environment.getPreParameters().get(n); + + // ReadPre reads from the start of the arguments array + + final ReadPreArgumentNode readArgumentNode = new ReadPreArgumentNode(context, sourceSection, n, false); + + final WriteLocalVariableNode writeLocal = WriteLocalVariableNodeFactory.create(context, sourceSection, param, readArgumentNode); + + loadIndividualArgumentsNodes.add(writeLocal); + } + + for (int n = 0; n < environment.getOptionalParameters().size(); n++) { + final FrameSlot param = environment.getOptionalParameters().get(n); + final RubyNode defaultValue = environment.getOptionalParametersDefaultValues().get(param); + + /* + * ReadOptional reads from the start of the arguments array, as long as it is long + * enough, else uses the default value (which may use locals with arguments just loaded, + * either from pre or preceding optionals). + */ + + final ReadOptionalArgumentNode readArgumentNode = new ReadOptionalArgumentNode(context, body.getEncapsulatingSourceSection(), preCount + n, preCount + postCount + n + 1, + (RubyNode) defaultValue.copy()); + + final WriteLocalVariableNode writeLocal = WriteLocalVariableNodeFactory.create(context, sourceSection, param, readArgumentNode); + + loadIndividualArgumentsNodes.add(writeLocal); + } + + for (int n = 0; n < environment.getPostParameters().size(); n++) { + final FrameSlot param = environment.getPostParameters().get(n); + + // ReadPost reads from the end of the arguments array + + final ReadPostArgumentNode readArgumentNode = new ReadPostArgumentNode(context, sourceSection, postCount - n - 1); + + final WriteLocalVariableNode writeLocal = WriteLocalVariableNodeFactory.create(context, sourceSection, param, readArgumentNode); + + loadIndividualArgumentsNodes.add(writeLocal); + } + + if (environment.getRestParameter() != null) { + /* + * TODO(cs): this assumes there are no optionals and therefore also no posts, which may + * not be a valid assumption. + */ + + if (postCount != 0) { + context.implementationMessage("post arguments as well as a rest argument - they will conflict"); + } + + final ReadRestArgumentNode readArgumentNode = new ReadRestArgumentNode(context, sourceSection, preCount); + + final WriteLocalVariableNode writeLocal = WriteLocalVariableNodeFactory.create(context, sourceSection, environment.getRestParameter(), readArgumentNode); + + loadIndividualArgumentsNodes.add(writeLocal); + } + + if (environment.getBlockParameter() != null) { + final FrameSlot param = environment.getBlockParameter(); + + final ReadBlockArgumentNode readArgumentNode = new ReadBlockArgumentNode(context, sourceSection, false); + + final WriteLocalVariableNode writeLocal = WriteLocalVariableNodeFactory.create(context, sourceSection, param, readArgumentNode); + + loadIndividualArgumentsNodes.add(writeLocal); + } + + final RubyNode loadIndividualArguments = new SequenceNode(context, sourceSection, loadIndividualArgumentsNodes.toArray(new RubyNode[loadIndividualArgumentsNodes.size()])); + + final RubyNode noSwitch = new SequenceNode(context, body.getSourceSection(), loadIndividualArguments, body); + + if (!isBlock) { + return noSwitch; + } + + /* + * See the test testBlockArgumentsDestructure for a motivation for this. See + * BlockDestructureSwitchNode for how it works. + */ + + if (preCount + postCount == 1 && environment.getOptionalParameters().size() == 0) { + return noSwitch; + } + + final List destructureLoadArgumentsNodes = new ArrayList<>(); + + for (int n = 0; n < environment.getPreParameters().size(); n++) { + final FrameSlot param = environment.getPreParameters().get(n); + + final ReadDestructureArgumentNode readArgumentNode = new ReadDestructureArgumentNode(context, sourceSection, n); + + final WriteLocalVariableNode writeLocal = WriteLocalVariableNodeFactory.create(context, sourceSection, param, readArgumentNode); + + destructureLoadArgumentsNodes.add(writeLocal); + } + + final RubyNode destructureLoadArguments = new SequenceNode(context, body.getSourceSection(), destructureLoadArgumentsNodes.toArray(new RubyNode[destructureLoadArgumentsNodes.size()])); + + return new BlockDestructureSwitchNode(context, body.getEncapsulatingSourceSection(), loadIndividualArguments, destructureLoadArguments, body); + + } + + private Arity findParameters(org.jrubyparser.ast.ArgsNode args) { + if (args == null) { + return Arity.NO_ARGS; + } + + final SourceSection sourceSection = translate(args.getPosition()); + + if (args.getPre() != null) { + for (org.jrubyparser.ast.Node arg : args.getPre().childNodes()) { + if (arg instanceof org.jrubyparser.ast.ArgumentNode) { + final org.jrubyparser.ast.ArgumentNode argNode = (org.jrubyparser.ast.ArgumentNode) arg; + environment.getPreParameters().add(environment.declareVar(argNode.getName())); + } else if (arg instanceof org.jrubyparser.ast.MultipleAsgnNode) { + /* + * TODO(cs): I don't know how to handle this yet, so I just do my best to get + * the names out and define them so the rest of the parser succeeds. + */ + + context.implementationMessage("only extracting names from multiple assignment in arguments"); + + final org.jrubyparser.ast.MultipleAsgnNode multAsgn = (org.jrubyparser.ast.MultipleAsgnNode) arg; + + final List names = new ArrayList<>(); + getNamesFromMultipleAssignment(multAsgn, names); + + for (String name : names) { + environment.getPreParameters().add(environment.declareVar(name)); + } + } + } + } + + // The JRuby parser expresses optional arguments as a block of local assignments + + /* + * Note that default values for optional params can refer to the actual value of previous + * args, so be careful with the order of args here and in loadArgumentsIntoLocals. + */ + + if (args.getOptional() != null) { + for (org.jrubyparser.ast.Node arg : args.getOptional().childNodes()) { + final org.jrubyparser.ast.OptArgNode optArgNode = (org.jrubyparser.ast.OptArgNode) arg; + + String name; + org.jrubyparser.ast.Node valueNode; + + if (optArgNode.getValue() instanceof org.jrubyparser.ast.LocalAsgnNode) { + final org.jrubyparser.ast.LocalAsgnNode optLocalAsgn = (org.jrubyparser.ast.LocalAsgnNode) optArgNode.getValue(); + name = optLocalAsgn.getName(); + valueNode = optLocalAsgn.getValue(); + } else if (optArgNode.getValue() instanceof org.jrubyparser.ast.DAsgnNode) { + final org.jrubyparser.ast.DAsgnNode optLocalAsgn = (org.jrubyparser.ast.DAsgnNode) optArgNode.getValue(); + name = optLocalAsgn.getName(); + valueNode = optLocalAsgn.getValue(); + } else { + throw new UnsupportedOperationException(optArgNode.getValue().getClass().getName()); + } + + RubyNode paramDefaultValue; + + if (valueNode == null) { + paramDefaultValue = new NilNode(context, sourceSection); + } else { + paramDefaultValue = (RubyNode) valueNode.accept(this); + } + + final FrameSlot frameSlot = environment.declareVar(name); + environment.getOptionalParameters().add(frameSlot); + environment.getOptionalParametersDefaultValues().put(frameSlot, paramDefaultValue); + } + } + + if (args.getPost() != null) { + for (org.jrubyparser.ast.Node arg : args.getPost().childNodes()) { + final org.jrubyparser.ast.ArgumentNode argNode = (org.jrubyparser.ast.ArgumentNode) arg; + environment.getPostParameters().add(environment.declareVar(argNode.getName())); + } + } + + if (args.getRest() != null) { + final org.jrubyparser.ast.RestArgNode rest = (org.jrubyparser.ast.RestArgNode) args.getRest(); + environment.setRestParameter(environment.declareVar(rest.getName())); + } + + if (args.getBlock() != null) { + final org.jrubyparser.ast.BlockArgNode blockArgNode = args.getBlock(); + final FrameSlot frameSlot = environment.declareVar(blockArgNode.getName()); + environment.setBlockParameter(frameSlot); + } + + final int minimum = environment.getPreParameters().size() + environment.getPostParameters().size(); + + int maximum = minimum + environment.getOptionalParameters().size(); + + if (args.getRest() != null) { + maximum = Arity.NO_MAXIMUM; + } + + return new Arity(minimum, maximum); + } + + private void getNamesFromMultipleAssignment(org.jrubyparser.ast.MultipleAsgnNode multAsgn, List names) { + for (org.jrubyparser.ast.Node a : multAsgn.getPre().childNodes()) { + if (a instanceof org.jrubyparser.ast.DAsgnNode) { + names.add(((org.jrubyparser.ast.DAsgnNode) a).getName()); + } else if (a instanceof org.jrubyparser.ast.MultipleAsgnNode) { + getNamesFromMultipleAssignment((org.jrubyparser.ast.MultipleAsgnNode) a, names); + } else if (a instanceof org.jrubyparser.ast.LocalAsgnNode) { + names.add(((org.jrubyparser.ast.LocalAsgnNode) a).getName()); + } else { + throw new RuntimeException(a.getClass().getName()); + } + } + } + + @Override + public Object visitSuperNode(org.jrubyparser.ast.SuperNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + final ArgumentsAndBlockTranslation argumentsAndBlock = translateArgumentsAndBlock(sourceSection, node.getIter(), node.getArgs(), null); + + final String name = environment.getMethodName(); + + return new GeneralSuperCallNode(context, sourceSection, name, argumentsAndBlock.getBlock(), argumentsAndBlock.getArguments(), argumentsAndBlock.isSplatted()); + } + + @Override + public Object visitZSuperNode(org.jrubyparser.ast.ZSuperNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + final ArgumentsAndBlockTranslation argumentsAndBlock = translateArgumentsAndBlock(sourceSection, node.getIter(), null, null); + + final String name = environment.getMethodName(); + + return new GeneralSuperCallNode(context, sourceSection, name, argumentsAndBlock.getBlock(), argumentsAndBlock.getArguments(), argumentsAndBlock.isSplatted()); + } + + @Override + protected FlipFlopStateNode createFlipFlopState(SourceSection sourceSection, int depth) { + if (isBlock) { + environment.setNeedsDeclarationFrame(); + return parent.createFlipFlopState(sourceSection, depth + 1); + } else { + return super.createFlipFlopState(sourceSection, depth); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/ModuleTranslator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/ModuleTranslator.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.parser; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.nodes.constants.*; +import com.oracle.truffle.ruby.nodes.control.*; +import com.oracle.truffle.ruby.nodes.literal.*; +import com.oracle.truffle.ruby.nodes.methods.*; +import com.oracle.truffle.ruby.nodes.objects.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +/** + * Translates module and class nodes. + *

+ * In Ruby, a module or class definition is somewhat like a method. It has a local scope and a value + * for self, which is the module or class object that is being defined. Therefore for a module or + * class definition we translate into a special method. We run that method with self set to be the + * newly allocated module or class. We then have to treat at least method and constant definitions + * differently. + */ +class ModuleTranslator extends Translator { + + public ModuleTranslator(RubyContext context, Translator parent, TranslatorEnvironment environment, Source source) { + super(context, parent, environment, source); + } + + public MethodDefinitionNode compileClassNode(org.jrubyparser.SourcePosition sourcePosition, String name, org.jrubyparser.ast.Node bodyNode) { + final SourceSection sourceSection = translate(sourcePosition); + + environment.addMethodDeclarationSlots(); + + final String methodName = "(" + name + "-def" + ")"; + environment.setMethodName(methodName); + + RubyNode body; + + if (bodyNode != null) { + body = (RubyNode) bodyNode.accept(this); + } else { + body = new NilNode(context, sourceSection); + } + + if (environment.getFlipFlopStates().size() > 0) { + body = new SequenceNode(context, sourceSection, initFlipFlopStates(sourceSection), body); + } + + body = new CatchReturnNode(context, sourceSection, body, environment.getReturnID()); + + final RubyRootNode pristineRootNode = new RubyRootNode(sourceSection, methodName, body); + + final CallTarget callTarget = Truffle.getRuntime().createCallTarget(NodeUtil.cloneNode(pristineRootNode), environment.getFrameDescriptor()); + + return new MethodDefinitionNode(context, sourceSection, methodName, environment.getUniqueMethodIdentifier(), environment.getFrameDescriptor(), environment.needsDeclarationFrame(), + pristineRootNode, callTarget); + } + + @Override + public Object visitConstDeclNode(org.jrubyparser.ast.ConstDeclNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + final SelfNode selfNode = new SelfNode(context, sourceSection); + + return new WriteConstantNode(context, sourceSection, node.getName(), selfNode, (RubyNode) node.getValue().accept(this)); + } + + @Override + public Object visitConstNode(org.jrubyparser.ast.ConstNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + final SelfNode selfNode = new SelfNode(context, sourceSection); + + return new UninitializedReadConstantNode(context, sourceSection, node.getName(), selfNode); + } + + @Override + public Object visitDefnNode(org.jrubyparser.ast.DefnNode node) { + /* + * The top-level translator puts methods into Object. We put ours into the self, which is + * the class being defined. + */ + + final TranslatorEnvironment newEnvironment = new TranslatorEnvironment(context, environment, environment.getParser(), environment.getParser().allocateReturnID(), true, true, + new UniqueMethodIdentifier()); + final MethodTranslator methodCompiler = new MethodTranslator(context, this, newEnvironment, false, source); + final MethodDefinitionNode functionExprNode = methodCompiler.compileFunctionNode(translate(node.getPosition()), node.getName(), node.getArgs(), node.getBody()); + + final SourceSection sourceSection = translate(node.getPosition()); + return new AddMethodNode(context, sourceSection, new SelfNode(context, sourceSection), functionExprNode); + } + + @Override + public Object visitClassVarAsgnNode(org.jrubyparser.ast.ClassVarAsgnNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + final RubyNode receiver = new SelfNode(context, sourceSection); + + final RubyNode rhs = (RubyNode) node.getValue().accept(this); + + return new WriteClassVariableNode(context, sourceSection, node.getName(), receiver, rhs); + } + + @Override + public Object visitClassVarNode(org.jrubyparser.ast.ClassVarNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + return new ReadClassVariableNode(context, sourceSection, node.getName(), new SelfNode(context, sourceSection)); + } + + @Override + public Object visitAliasNode(org.jrubyparser.ast.AliasNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + final org.jrubyparser.ast.LiteralNode oldName = (org.jrubyparser.ast.LiteralNode) node.getOldName(); + final org.jrubyparser.ast.LiteralNode newName = (org.jrubyparser.ast.LiteralNode) node.getNewName(); + + return new AliasNode(context, sourceSection, new SelfNode(context, sourceSection), newName.getName(), oldName.getName()); + } + + @Override + protected RubyNode getModuleToDefineModulesIn(SourceSection sourceSection) { + return new SelfNode(context, sourceSection); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/RubyFrameTypeConversion.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/RubyFrameTypeConversion.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.parser; + +import com.oracle.truffle.api.impl.*; +import com.oracle.truffle.ruby.runtime.*; + +public final class RubyFrameTypeConversion extends DefaultFrameTypeConversion { + + private static final RubyFrameTypeConversion INSTANCE = new RubyFrameTypeConversion(); + + private RubyFrameTypeConversion() { + } + + @Override + public Object getDefaultValue() { + return NilPlaceholder.INSTANCE; + } + + public static RubyFrameTypeConversion getInstance() { + return INSTANCE; + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/Translator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/Translator.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,2093 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.parser; + +import java.math.*; +import java.util.*; +import java.util.regex.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.impl.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.nodes.call.*; +import com.oracle.truffle.ruby.nodes.cast.*; +import com.oracle.truffle.ruby.nodes.constants.*; +import com.oracle.truffle.ruby.nodes.control.*; +import com.oracle.truffle.ruby.nodes.core.*; +import com.oracle.truffle.ruby.nodes.debug.*; +import com.oracle.truffle.ruby.nodes.literal.*; +import com.oracle.truffle.ruby.nodes.literal.array.*; +import com.oracle.truffle.ruby.nodes.methods.*; +import com.oracle.truffle.ruby.nodes.methods.locals.*; +import com.oracle.truffle.ruby.nodes.objects.*; +import com.oracle.truffle.ruby.nodes.objects.instancevariables.*; +import com.oracle.truffle.ruby.nodes.yield.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.range.*; +import com.oracle.truffle.ruby.runtime.debug.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +/** + * A JRuby parser node visitor which translates JRuby AST nodes into our Ruby nodes, implementing a + * Ruby parser. Therefore there is some namespace contention here! We make all references to JRuby + * explicit. This is the only place though - it doesn't leak out elsewhere. + */ +public class Translator implements org.jrubyparser.NodeVisitor { + + protected final Translator parent; + + protected final RubyContext context; + protected final TranslatorEnvironment environment; + protected final Source source; + + private boolean translatingForStatement = false; + + private static final Map nodeDefinedNames = new HashMap<>(); + + static { + nodeDefinedNames.put(org.jrubyparser.ast.SelfNode.class, "self"); + nodeDefinedNames.put(org.jrubyparser.ast.NilNode.class, "nil"); + nodeDefinedNames.put(org.jrubyparser.ast.TrueNode.class, "true"); + nodeDefinedNames.put(org.jrubyparser.ast.FalseNode.class, "false"); + nodeDefinedNames.put(org.jrubyparser.ast.LocalAsgnNode.class, "assignment"); + nodeDefinedNames.put(org.jrubyparser.ast.DAsgnNode.class, "assignment"); + nodeDefinedNames.put(org.jrubyparser.ast.GlobalAsgnNode.class, "assignment"); + nodeDefinedNames.put(org.jrubyparser.ast.InstAsgnNode.class, "assignment"); + nodeDefinedNames.put(org.jrubyparser.ast.ClassVarAsgnNode.class, "assignment"); + nodeDefinedNames.put(org.jrubyparser.ast.OpAsgnAndNode.class, "assignment"); + nodeDefinedNames.put(org.jrubyparser.ast.OpAsgnOrNode.class, "assignment"); + nodeDefinedNames.put(org.jrubyparser.ast.OpAsgnNode.class, "assignment"); + nodeDefinedNames.put(org.jrubyparser.ast.OpElementAsgnNode.class, "assignment"); + nodeDefinedNames.put(org.jrubyparser.ast.MultipleAsgnNode.class, "assignment"); + nodeDefinedNames.put(org.jrubyparser.ast.GlobalVarNode.class, "global-variable"); + nodeDefinedNames.put(org.jrubyparser.ast.StrNode.class, "expression"); + nodeDefinedNames.put(org.jrubyparser.ast.DStrNode.class, "expression"); + nodeDefinedNames.put(org.jrubyparser.ast.FixnumNode.class, "expression"); + nodeDefinedNames.put(org.jrubyparser.ast.BignumNode.class, "expression"); + nodeDefinedNames.put(org.jrubyparser.ast.FloatNode.class, "expression"); + nodeDefinedNames.put(org.jrubyparser.ast.RegexpNode.class, "expression"); + nodeDefinedNames.put(org.jrubyparser.ast.DRegexpNode.class, "expression"); + nodeDefinedNames.put(org.jrubyparser.ast.ArrayNode.class, "expression"); + nodeDefinedNames.put(org.jrubyparser.ast.HashNode.class, "expression"); + nodeDefinedNames.put(org.jrubyparser.ast.SymbolNode.class, "expression"); + nodeDefinedNames.put(org.jrubyparser.ast.DotNode.class, "expression"); + nodeDefinedNames.put(org.jrubyparser.ast.NotNode.class, "expression"); + nodeDefinedNames.put(org.jrubyparser.ast.AndNode.class, "expression"); + nodeDefinedNames.put(org.jrubyparser.ast.OrNode.class, "expression"); + nodeDefinedNames.put(org.jrubyparser.ast.LocalVarNode.class, "local-variable"); + nodeDefinedNames.put(org.jrubyparser.ast.DVarNode.class, "local-variable"); + } + + /** + * Global variables which in common usage have frame local semantics. + */ + public static final Set FRAME_LOCAL_GLOBAL_VARIABLES = new HashSet<>(Arrays.asList("$_")); + + public Translator(RubyContext context, Translator parent, TranslatorEnvironment environment, Source source) { + this.context = context; + this.parent = parent; + this.environment = environment; + this.source = source; + } + + @Override + public Object visitAliasNode(org.jrubyparser.ast.AliasNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + final org.jrubyparser.ast.LiteralNode oldName = (org.jrubyparser.ast.LiteralNode) node.getOldName(); + final org.jrubyparser.ast.LiteralNode newName = (org.jrubyparser.ast.LiteralNode) node.getNewName(); + + final ClassNode classNode = new ClassNode(context, sourceSection, new SelfNode(context, sourceSection)); + + return new AliasNode(context, sourceSection, classNode, newName.getName(), oldName.getName()); + } + + @Override + public Object visitAndNode(org.jrubyparser.ast.AndNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + RubyNode x; + + if (node.getFirst() == null) { + x = new NilNode(context, sourceSection); + } else { + x = (RubyNode) node.getFirst().accept(this); + } + + RubyNode y; + + if (node.getSecond() == null) { + y = new NilNode(context, sourceSection); + } else { + y = (RubyNode) node.getSecond().accept(this); + } + + return AndNodeFactory.create(context, sourceSection, x, y); + } + + @Override + public Object visitArgsCatNode(org.jrubyparser.ast.ArgsCatNode node) { + final List nodes = new ArrayList<>(); + collectArgsCatNodes(nodes, node); + + final List translatedNodes = new ArrayList<>(); + + for (org.jrubyparser.ast.Node catNode : nodes) { + translatedNodes.add((RubyNode) catNode.accept(this)); + } + + return new ArrayConcatNode(context, translate(node.getPosition()), translatedNodes.toArray(new RubyNode[translatedNodes.size()])); + } + + // ArgsCatNodes can be nested - this collects them into a flat list of children + private void collectArgsCatNodes(List nodes, org.jrubyparser.ast.ArgsCatNode node) { + if (node.getFirst() instanceof org.jrubyparser.ast.ArgsCatNode) { + collectArgsCatNodes(nodes, (org.jrubyparser.ast.ArgsCatNode) node.getFirst()); + } else { + nodes.add(node.getFirst()); + } + + if (node.getSecond() instanceof org.jrubyparser.ast.ArgsCatNode) { + collectArgsCatNodes(nodes, (org.jrubyparser.ast.ArgsCatNode) node.getSecond()); + } else { + nodes.add(node.getSecond()); + } + } + + @Override + public Object visitArgsNode(org.jrubyparser.ast.ArgsNode node) { + return unimplemented(node); + } + + @Override + public Object visitArgsPushNode(org.jrubyparser.ast.ArgsPushNode node) { + return new ArrayPushNode(context, translate(node.getPosition()), (RubyNode) node.getFirstNode().accept(this), (RubyNode) node.getSecondNode().accept(this)); + } + + @Override + public Object visitArrayNode(org.jrubyparser.ast.ArrayNode node) { + final List values = node.childNodes(); + + final RubyNode[] translatedValues = new RubyNode[values.size()]; + + for (int n = 0; n < values.size(); n++) { + translatedValues[n] = (RubyNode) values.get(n).accept(this); + } + + return new UninitialisedArrayLiteralNode(context, translate(node.getPosition()), translatedValues); + } + + @Override + public Object visitAttrAssignNode(org.jrubyparser.ast.AttrAssignNode node) { + return visitAttrAssignNodeExtraArgument(node, null); + } + + /** + * See translateDummyAssignment to understand what this is for. + */ + public RubyNode visitAttrAssignNodeExtraArgument(org.jrubyparser.ast.AttrAssignNode node, RubyNode extraArgument) { + final org.jrubyparser.ast.CallNode callNode = new org.jrubyparser.ast.CallNode(node.getPosition(), node.getReceiver(), node.getName(), node.getArgs()); + return visitCallNodeExtraArgument(callNode, extraArgument); + } + + @Override + public Object visitBackRefNode(org.jrubyparser.ast.BackRefNode node) { + return unimplemented(node); + } + + @Override + public Object visitBeginNode(org.jrubyparser.ast.BeginNode node) { + return node.getBody().accept(this); + } + + @Override + public Object visitBignumNode(org.jrubyparser.ast.BignumNode node) { + return new BignumLiteralNode(context, translate(node.getPosition()), node.getValue()); + } + + @Override + public Object visitBlockArg18Node(org.jrubyparser.ast.BlockArg18Node node) { + return unimplemented(node); + } + + @Override + public Object visitBlockArgNode(org.jrubyparser.ast.BlockArgNode node) { + return unimplemented(node); + } + + @Override + public Object visitBlockNode(org.jrubyparser.ast.BlockNode node) { + final List children = node.childNodes(); + + final List translatedChildren = new ArrayList<>(); + + for (int n = 0; n < children.size(); n++) { + final RubyNode translatedChild = (RubyNode) children.get(n).accept(this); + + if (!(translatedChild instanceof DeadNode)) { + translatedChildren.add(translatedChild); + } + } + + if (translatedChildren.size() == 1) { + return translatedChildren.get(0); + } else { + return new SequenceNode(context, translate(node.getPosition()), translatedChildren.toArray(new RubyNode[translatedChildren.size()])); + } + } + + @Override + public Object visitBlockPassNode(org.jrubyparser.ast.BlockPassNode node) { + return unimplemented(node); + } + + @Override + public Object visitBreakNode(org.jrubyparser.ast.BreakNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + RubyNode resultNode; + + if (node.getValueNode() == null) { + resultNode = new NilNode(context, sourceSection); + } else { + resultNode = (RubyNode) node.getValueNode().accept(this); + } + + return new BreakNode(context, sourceSection, resultNode); + } + + @Override + public Object visitCallNode(org.jrubyparser.ast.CallNode node) { + return visitCallNodeExtraArgument(node, null); + } + + /** + * See translateDummyAssignment to understand what this is for. + */ + public RubyNode visitCallNodeExtraArgument(org.jrubyparser.ast.CallNode node, RubyNode extraArgument) { + final SourceSection sourceSection = translate(node.getPosition()); + + final RubyNode receiverTranslated = (RubyNode) node.getReceiver().accept(this); + + org.jrubyparser.ast.Node args = node.getArgs(); + org.jrubyparser.ast.Node block = node.getIter(); + + if (block == null && args instanceof org.jrubyparser.ast.IterNode) { + final org.jrubyparser.ast.Node temp = args; + args = block; + block = temp; + } + + final ArgumentsAndBlockTranslation argumentsAndBlock = translateArgumentsAndBlock(sourceSection, block, args, extraArgument); + + return new CallNode(context, sourceSection, node.getName(), receiverTranslated, argumentsAndBlock.getBlock(), argumentsAndBlock.isSplatted(), argumentsAndBlock.getArguments()); + } + + protected class ArgumentsAndBlockTranslation { + + private final RubyNode block; + private final RubyNode[] arguments; + private final boolean isSplatted; + + public ArgumentsAndBlockTranslation(RubyNode block, RubyNode[] arguments, boolean isSplatted) { + super(); + this.block = block; + this.arguments = arguments; + this.isSplatted = isSplatted; + } + + public RubyNode getBlock() { + return block; + } + + public RubyNode[] getArguments() { + return arguments; + } + + public boolean isSplatted() { + return isSplatted; + } + + } + + protected ArgumentsAndBlockTranslation translateArgumentsAndBlock(SourceSection sourceSection, org.jrubyparser.ast.Node iterNode, org.jrubyparser.ast.Node argsNode, RubyNode extraArgument) { + assert !(argsNode instanceof org.jrubyparser.ast.IterNode); + + final List arguments = new ArrayList<>(); + org.jrubyparser.ast.Node blockPassNode = null; + + boolean isSplatted = false; + + if (argsNode instanceof org.jrubyparser.ast.ListNode) { + arguments.addAll(((org.jrubyparser.ast.ListNode) argsNode).childNodes()); + } else if (argsNode instanceof org.jrubyparser.ast.BlockPassNode) { + final org.jrubyparser.ast.BlockPassNode blockPass = (org.jrubyparser.ast.BlockPassNode) argsNode; + + final org.jrubyparser.ast.Node blockPassArgs = blockPass.getArgs(); + + if (blockPassArgs instanceof org.jrubyparser.ast.ListNode) { + arguments.addAll(((org.jrubyparser.ast.ListNode) blockPassArgs).childNodes()); + } else if (blockPassArgs instanceof org.jrubyparser.ast.ArgsCatNode) { + arguments.add(blockPassArgs); + } else if (blockPassArgs != null) { + throw new UnsupportedOperationException("Don't know how to block pass " + blockPassArgs); + } + + blockPassNode = blockPass.getBody(); + } else if (argsNode instanceof org.jrubyparser.ast.SplatNode) { + isSplatted = true; + arguments.add(argsNode); + } else if (argsNode instanceof org.jrubyparser.ast.ArgsCatNode) { + isSplatted = true; + arguments.add(argsNode); + } else if (argsNode != null) { + isSplatted = true; + arguments.add(argsNode); + } + + RubyNode blockTranslated; + + if (blockPassNode != null && iterNode != null) { + throw new UnsupportedOperationException("Don't know how to pass both an block and a block-pass argument"); + } else if (iterNode != null) { + blockTranslated = (BlockDefinitionNode) iterNode.accept(this); + } else if (blockPassNode != null) { + blockTranslated = ProcCastNodeFactory.create(context, sourceSection, (RubyNode) blockPassNode.accept(this)); + } else { + blockTranslated = null; + } + + final List argumentsTranslated = new ArrayList<>(); + + for (org.jrubyparser.ast.Node argument : arguments) { + argumentsTranslated.add((RubyNode) argument.accept(this)); + } + + if (extraArgument != null) { + argumentsTranslated.add(extraArgument); + } + + final RubyNode[] argumentsTranslatedArray = argumentsTranslated.toArray(new RubyNode[argumentsTranslated.size()]); + + return new ArgumentsAndBlockTranslation(blockTranslated, argumentsTranslatedArray, isSplatted); + } + + @Override + public Object visitCaseNode(org.jrubyparser.ast.CaseNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + RubyNode elseNode; + + if (node.getElse() != null) { + elseNode = (RubyNode) node.getElse().accept(this); + } else { + elseNode = new NilNode(context, sourceSection); + } + + /* + * There are two sorts of case - one compares a list of expressions against a value, the + * other just checks a list of expressions for truth. + */ + + if (node.getCase() != null) { + // Evaluate the case expression and store it in a local + + final String tempName = environment.allocateLocalTemp(); + + final RubyNode readTemp = environment.findLocalVarNode(tempName, sourceSection); + + final RubyNode assignTemp = ((ReadNode) readTemp).makeWriteNode((RubyNode) node.getCase().accept(this)); + + /* + * Build an if expression from the whens and else. Work backwards because the first if + * contains all the others in its else clause. + */ + + for (int n = node.getCases().size() - 1; n >= 0; n--) { + final org.jrubyparser.ast.WhenNode when = (org.jrubyparser.ast.WhenNode) node.getCases().get(n); + + // Make a condition from the one or more expressions combined in an or expression + + final List expressions; + + if (when.getExpression() instanceof org.jrubyparser.ast.ListNode) { + expressions = ((org.jrubyparser.ast.ListNode) when.getExpression()).childNodes(); + } else { + expressions = Arrays.asList(when.getExpression()); + } + + final List comparisons = new ArrayList<>(); + + for (org.jrubyparser.ast.Node expressionNode : expressions) { + final RubyNode rubyExpression = (RubyNode) expressionNode.accept(this); + + final CallNode comparison = new CallNode(context, sourceSection, "===", rubyExpression, null, false, new RubyNode[]{environment.findLocalVarNode(tempName, sourceSection)}); + + comparisons.add(comparison); + } + + RubyNode conditionNode = comparisons.get(comparisons.size() - 1); + + // As with the if nodes, we work backwards to make it left associative + + for (int i = comparisons.size() - 2; i >= 0; i--) { + conditionNode = OrNodeFactory.create(context, sourceSection, comparisons.get(i), conditionNode); + } + + // Create the if node + + final BooleanCastNode conditionCastNode = BooleanCastNodeFactory.create(context, sourceSection, conditionNode); + + RubyNode thenNode; + + if (when.getBody() == null) { + thenNode = new NilNode(context, sourceSection); + } else { + thenNode = (RubyNode) when.getBody().accept(this); + } + + final IfNode ifNode = new IfNode(context, sourceSection, conditionCastNode, thenNode, elseNode); + + // This if becomes the else for the next if + + elseNode = ifNode; + } + + final RubyNode ifNode = elseNode; + + // A top-level block assigns the temp then runs the if + + return new SequenceNode(context, sourceSection, assignTemp, ifNode); + } else { + for (int n = node.getCases().size() - 1; n >= 0; n--) { + final org.jrubyparser.ast.WhenNode when = (org.jrubyparser.ast.WhenNode) node.getCases().get(n); + + // Make a condition from the one or more expressions combined in an or expression + + final List expressions; + + if (when.getExpression() instanceof org.jrubyparser.ast.ListNode) { + expressions = ((org.jrubyparser.ast.ListNode) when.getExpression()).childNodes(); + } else { + expressions = Arrays.asList(when.getExpression()); + } + + final List tests = new ArrayList<>(); + + for (org.jrubyparser.ast.Node expressionNode : expressions) { + final RubyNode rubyExpression = (RubyNode) expressionNode.accept(this); + tests.add(rubyExpression); + } + + RubyNode conditionNode = tests.get(tests.size() - 1); + + // As with the if nodes, we work backwards to make it left associative + + for (int i = tests.size() - 2; i >= 0; i--) { + conditionNode = OrNodeFactory.create(context, sourceSection, tests.get(i), conditionNode); + } + + // Create the if node + + final BooleanCastNode conditionCastNode = BooleanCastNodeFactory.create(context, sourceSection, conditionNode); + + final RubyNode thenNode = (RubyNode) when.getBody().accept(this); + + final IfNode ifNode = new IfNode(context, sourceSection, conditionCastNode, thenNode, elseNode); + + // This if becomes the else for the next if + + elseNode = ifNode; + } + + return elseNode; + } + } + + @Override + public Object visitClassNode(org.jrubyparser.ast.ClassNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + final String name = node.getCPath().getName(); + + final TranslatorEnvironment newEnvironment = new TranslatorEnvironment(context, environment, environment.getParser(), environment.getParser().allocateReturnID(), true, true, + new UniqueMethodIdentifier()); + final ModuleTranslator classTranslator = new ModuleTranslator(context, this, newEnvironment, source); + + final MethodDefinitionNode definitionMethod = classTranslator.compileClassNode(node.getPosition(), node.getCPath().getName(), node.getBody()); + + /* + * See my note in visitDefnNode about where the class gets defined - the same applies here. + */ + + RubyNode superClass; + + if (node.getSuper() != null) { + superClass = (RubyNode) node.getSuper().accept(this); + } else { + superClass = new ObjectLiteralNode(context, sourceSection, context.getCoreLibrary().getObjectClass()); + } + + final DefineOrGetClassNode defineOrGetClass = new DefineOrGetClassNode(context, sourceSection, name, getModuleToDefineModulesIn(sourceSection), superClass); + + return new OpenModuleNode(context, sourceSection, defineOrGetClass, definitionMethod); + } + + protected RubyNode getModuleToDefineModulesIn(SourceSection sourceSection) { + return new ClassNode(context, sourceSection, new SelfNode(context, sourceSection)); + } + + @Override + public Object visitClassVarAsgnNode(org.jrubyparser.ast.ClassVarAsgnNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + final RubyNode receiver = new ClassNode(context, sourceSection, new SelfNode(context, sourceSection)); + + final RubyNode rhs = (RubyNode) node.getValue().accept(this); + + return new WriteClassVariableNode(context, sourceSection, node.getName(), receiver, rhs); + } + + @Override + public Object visitClassVarDeclNode(org.jrubyparser.ast.ClassVarDeclNode node) { + return unimplemented(node); + } + + @Override + public Object visitClassVarNode(org.jrubyparser.ast.ClassVarNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + return new ReadClassVariableNode(context, sourceSection, node.getName(), new SelfNode(context, sourceSection)); + } + + @Override + public Object visitColon2Node(org.jrubyparser.ast.Colon2Node node) { + final RubyNode lhs = (RubyNode) node.getLeftNode().accept(this); + + return new UninitializedReadConstantNode(context, translate(node.getPosition()), node.getName(), lhs); + } + + @Override + public Object visitColon3Node(org.jrubyparser.ast.Colon3Node node) { + // Colon3 means the root namespace, as in ::Foo + + final SourceSection sourceSection = translate(node.getPosition()); + + final ObjectLiteralNode root = new ObjectLiteralNode(context, sourceSection, context.getCoreLibrary().getMainObject()); + + return new UninitializedReadConstantNode(context, sourceSection, node.getName(), root); + } + + @Override + public Object visitConstDeclNode(org.jrubyparser.ast.ConstDeclNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + final ClassNode classNode = new ClassNode(context, sourceSection, new SelfNode(context, sourceSection)); + + return new WriteConstantNode(context, sourceSection, node.getName(), classNode, (RubyNode) node.getValue().accept(this)); + } + + @Override + public Object visitConstNode(org.jrubyparser.ast.ConstNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + return new UninitializedReadConstantNode(context, sourceSection, node.getName(), new SelfNode(context, sourceSection)); + } + + @Override + public Object visitDAsgnNode(org.jrubyparser.ast.DAsgnNode node) { + return new org.jrubyparser.ast.LocalAsgnNode(node.getPosition(), node.getName(), node.getDepth(), node.getValue()).accept(this); + } + + @Override + public Object visitDRegxNode(org.jrubyparser.ast.DRegexpNode node) { + SourceSection sourceSection = translate(node.getPosition()); + + final RubyNode stringNode = translateInterpolatedString(sourceSection, node.childNodes()); + + return StringToRegexpNodeFactory.create(context, sourceSection, stringNode); + } + + @Override + public Object visitDStrNode(org.jrubyparser.ast.DStrNode node) { + return translateInterpolatedString(translate(node.getPosition()), node.childNodes()); + } + + @Override + public Object visitDSymbolNode(org.jrubyparser.ast.DSymbolNode node) { + SourceSection sourceSection = translate(node.getPosition()); + + final RubyNode stringNode = translateInterpolatedString(sourceSection, node.childNodes()); + + return StringToSymbolNodeFactory.create(context, sourceSection, stringNode); + } + + private RubyNode translateInterpolatedString(SourceSection sourceSection, List childNodes) { + final List children = new ArrayList<>(); + + for (org.jrubyparser.ast.Node child : childNodes) { + children.add((RubyNode) child.accept(this)); + } + + return new InterpolatedStringNode(context, sourceSection, children.toArray(new RubyNode[children.size()])); + } + + @Override + public Object visitDVarNode(org.jrubyparser.ast.DVarNode node) { + RubyNode readNode = environment.findLocalVarNode(node.getName(), translate(node.getPosition())); + + if (readNode == null) { + context.implementationMessage("can't find variable %s at %s, using noop", node.getName(), node.getPosition()); + readNode = new NilNode(context, translate(node.getPosition())); + } + + return readNode; + } + + @Override + public Object visitDXStrNode(org.jrubyparser.ast.DXStrNode node) { + SourceSection sourceSection = translate(node.getPosition()); + + final RubyNode string = translateInterpolatedString(sourceSection, node.childNodes()); + + return new SystemNode(context, sourceSection, string); + } + + @Override + public Object visitDefinedNode(org.jrubyparser.ast.DefinedNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + org.jrubyparser.ast.Node expressionNode = node.getExpression(); + + while (expressionNode instanceof org.jrubyparser.ast.NewlineNode) { + expressionNode = ((org.jrubyparser.ast.NewlineNode) expressionNode).getNextNode(); + } + + final String name = nodeDefinedNames.get(expressionNode.getClass()); + + if (name != null) { + final StringLiteralNode literal = new StringLiteralNode(context, sourceSection, name); + return literal; + } + + return new DefinedNode(context, sourceSection, (RubyNode) node.getExpression().accept(this)); + } + + @Override + public Object visitDefnNode(org.jrubyparser.ast.DefnNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + final ClassNode classNode = new ClassNode(context, sourceSection, new SelfNode(context, sourceSection)); + return translateMethodDefinition(sourceSection, classNode, node.getName(), node.getArgs(), node.getBody()); + } + + @Override + public Object visitDefsNode(org.jrubyparser.ast.DefsNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + final RubyNode objectNode = (RubyNode) node.getReceiver().accept(this); + + final SingletonClassNode singletonClassNode = new SingletonClassNode(context, sourceSection, objectNode); + + return translateMethodDefinition(sourceSection, singletonClassNode, node.getName(), node.getArgs(), node.getBody()); + } + + private RubyNode translateMethodDefinition(SourceSection sourceSection, RubyNode classNode, String methodName, org.jrubyparser.ast.ArgsNode argsNode, org.jrubyparser.ast.Node bodyNode) { + final TranslatorEnvironment newEnvironment = new TranslatorEnvironment(context, environment, environment.getParser(), environment.getParser().allocateReturnID(), true, true, + new UniqueMethodIdentifier()); + + // ownScopeForAssignments is the same for the defined method as the current one. + + final MethodTranslator methodCompiler = new MethodTranslator(context, this, newEnvironment, false, source); + + final MethodDefinitionNode functionExprNode = methodCompiler.compileFunctionNode(sourceSection, methodName, argsNode, bodyNode); + + /* + * In the top-level, methods are defined in the class of the main object. This is + * counter-intuitive - I would have expected them to be defined in the singleton class. + * Apparently this is a design decision to make top-level methods sort of global. + * + * http://stackoverflow.com/questions/1761148/where-are-methods-defined-at-the-ruby-top-level + */ + + return new AddMethodNode(context, sourceSection, classNode, functionExprNode); + } + + @Override + public Object visitDotNode(org.jrubyparser.ast.DotNode node) { + final RubyNode begin = (RubyNode) node.getBegin().accept(this); + final RubyNode end = (RubyNode) node.getEnd().accept(this); + SourceSection sourceSection = translate(node.getPosition()); + + if (begin instanceof FixnumLiteralNode && end instanceof FixnumLiteralNode) { + final int beginValue = ((FixnumLiteralNode) begin).getValue(); + final int endValue = ((FixnumLiteralNode) end).getValue(); + + return new ObjectLiteralNode(context, sourceSection, new FixnumRange(context.getCoreLibrary().getRangeClass(), beginValue, endValue, node.isExclusive())); + } + // See RangeNode for why there is a node specifically for creating this one type + return RangeLiteralNodeFactory.create(context, sourceSection, node.isExclusive(), begin, end); + } + + @Override + public Object visitEncodingNode(org.jrubyparser.ast.EncodingNode node) { + return unimplemented(node); + } + + @Override + public Object visitEnsureNode(org.jrubyparser.ast.EnsureNode node) { + final RubyNode tryPart = (RubyNode) node.getBody().accept(this); + final RubyNode ensurePart = (RubyNode) node.getEnsure().accept(this); + return new EnsureNode(context, translate(node.getPosition()), tryPart, ensurePart); + } + + @Override + public Object visitEvStrNode(org.jrubyparser.ast.EvStrNode node) { + return node.getBody().accept(this); + } + + @Override + public Object visitFCallNode(org.jrubyparser.ast.FCallNode node) { + final org.jrubyparser.ast.Node receiver = new org.jrubyparser.ast.SelfNode(node.getPosition()); + final org.jrubyparser.ast.Node callNode = new org.jrubyparser.ast.CallNode(node.getPosition(), receiver, node.getName(), node.getArgs(), node.getIter()); + + return callNode.accept(this); + } + + @Override + public Object visitFalseNode(org.jrubyparser.ast.FalseNode node) { + return new BooleanLiteralNode(context, translate(node.getPosition()), false); + } + + @Override + public Object visitFixnumNode(org.jrubyparser.ast.FixnumNode node) { + final long value = node.getValue(); + + if (value >= RubyFixnum.MIN_VALUE && value <= RubyFixnum.MAX_VALUE) { + return new FixnumLiteralNode(context, translate(node.getPosition()), (int) value); + } + return new BignumLiteralNode(context, translate(node.getPosition()), BigInteger.valueOf(value)); + } + + @Override + public Object visitFlipNode(org.jrubyparser.ast.FlipNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + final RubyNode begin = (RubyNode) node.getBegin().accept(this); + final RubyNode end = (RubyNode) node.getEnd().accept(this); + + final BooleanCastNode beginCast = BooleanCastNodeFactory.create(context, sourceSection, begin); + final BooleanCastNode endCast = BooleanCastNodeFactory.create(context, sourceSection, end); + final FlipFlopStateNode stateNode = createFlipFlopState(sourceSection, 0); + + return new FlipFlopNode(context, sourceSection, beginCast, endCast, stateNode, node.isExclusive()); + } + + protected FlipFlopStateNode createFlipFlopState(SourceSection sourceSection, int depth) { + final FrameSlot frameSlot = environment.declareVar(environment.allocateLocalTemp()); + environment.getFlipFlopStates().add(frameSlot); + + if (depth == 0) { + return new LocalFlipFlopStateNode(sourceSection, frameSlot); + } else { + return new LevelFlipFlopStateNode(sourceSection, depth, frameSlot); + } + } + + @Override + public Object visitFloatNode(org.jrubyparser.ast.FloatNode node) { + return new FloatLiteralNode(context, translate(node.getPosition()), node.getValue()); + } + + @Override + public Object visitForNode(org.jrubyparser.ast.ForNode node) { + /** + * A Ruby for-loop, such as: + * + *

+         * for x in y
+         *     z = x
+         *     puts z
+         * end
+         * 
+ * + * naively desugars to: + * + *
+         * y.each do |x|
+         *     z = x
+         *     puts z
+         * end
+         * 
+ * + * The main difference is that z is always going to be local to the scope outside the block, + * so it's a bit more like: + * + *
+         * z = nil unless z is already defined
+         * y.each do |x|
+         *    z = x
+         *    puts x
+         * end
+         * 
+ * + * Which forces z to be defined in the correct scope. The parser already correctly calls z a + * local, but then that causes us a problem as if we're going to translate to a block we + * need a formal parameter - not a local variable. My solution to this is to add a + * temporary: + * + *
+         * z = nil unless z is already defined
+         * y.each do |temp|
+         *    x = temp
+         *    z = x
+         *    puts x
+         * end
+         * 
+ * + * We also need that temp because the expression assigned in the for could be index + * assignment, multiple assignment, or whatever: + * + *
+         * for x[0] in y
+         *     z = x[0]
+         *     puts z
+         * end
+         * 
+ * + * http://blog.grayproductions.net/articles/the_evils_of_the_for_loop + * http://stackoverflow.com/questions/3294509/for-vs-each-in-ruby + * + * The other complication is that normal locals should be defined in the enclosing scope, + * unlike a normal block. We do that by setting a flag on this translator object when we + * visit the new iter, translatingForStatement, which we recognise when visiting an iter + * node. + * + * Finally, note that JRuby's terminology is strange here. Normally 'iter' is a different + * term for a block. Here, JRuby calls the object being iterated over the 'iter'. + */ + + final String temp = environment.allocateLocalTemp(); + + final org.jrubyparser.ast.Node receiver = node.getIter(); + + /* + * The x in for x in ... is like the nodes in multiple assignment - it has a dummy RHS which + * we need to replace with our temp. Just like in multiple assignment this is really awkward + * with the JRuby AST. + */ + + final org.jrubyparser.ast.LocalVarNode readTemp = new org.jrubyparser.ast.LocalVarNode(node.getPosition(), 0, temp); + final org.jrubyparser.ast.Node forVar = node.getVar(); + final org.jrubyparser.ast.Node assignTemp = setRHS(forVar, readTemp); + + final org.jrubyparser.ast.BlockNode bodyWithTempAssign = new org.jrubyparser.ast.BlockNode(node.getPosition()); + bodyWithTempAssign.add(assignTemp); + bodyWithTempAssign.add(node.getBody()); + + final org.jrubyparser.ast.ArgumentNode blockVar = new org.jrubyparser.ast.ArgumentNode(node.getPosition(), temp); + final org.jrubyparser.ast.ListNode blockArgsPre = new org.jrubyparser.ast.ListNode(node.getPosition(), blockVar); + final org.jrubyparser.ast.ArgsNode blockArgs = new org.jrubyparser.ast.ArgsNode(node.getPosition(), blockArgsPre, null, null, null, null, null, null); + final org.jrubyparser.ast.IterNode block = new org.jrubyparser.ast.IterNode(node.getPosition(), blockArgs, node.getScope(), bodyWithTempAssign); + + final org.jrubyparser.ast.CallNode callNode = new org.jrubyparser.ast.CallNode(node.getPosition(), receiver, "each", null, block); + + translatingForStatement = true; + final RubyNode translated = (RubyNode) callNode.accept(this); + translatingForStatement = false; + + return translated; + } + + private static org.jrubyparser.ast.Node setRHS(org.jrubyparser.ast.Node node, org.jrubyparser.ast.Node rhs) { + if (node instanceof org.jrubyparser.ast.LocalAsgnNode) { + final org.jrubyparser.ast.LocalAsgnNode localAsgnNode = (org.jrubyparser.ast.LocalAsgnNode) node; + return new org.jrubyparser.ast.LocalAsgnNode(node.getPosition(), localAsgnNode.getName(), 0, rhs); + } else if (node instanceof org.jrubyparser.ast.DAsgnNode) { + final org.jrubyparser.ast.DAsgnNode dAsgnNode = (org.jrubyparser.ast.DAsgnNode) node; + return new org.jrubyparser.ast.DAsgnNode(node.getPosition(), dAsgnNode.getName(), 0, rhs); + } else if (node instanceof org.jrubyparser.ast.MultipleAsgnNode) { + final org.jrubyparser.ast.MultipleAsgnNode multAsgnNode = (org.jrubyparser.ast.MultipleAsgnNode) node; + return new org.jrubyparser.ast.MultipleAsgnNode(node.getPosition(), multAsgnNode.getPre(), multAsgnNode.getRest(), multAsgnNode.getPost()); + } else if (node instanceof org.jrubyparser.ast.InstAsgnNode) { + final org.jrubyparser.ast.InstAsgnNode instAsgnNode = (org.jrubyparser.ast.InstAsgnNode) node; + return new org.jrubyparser.ast.InstAsgnNode(node.getPosition(), instAsgnNode.getName(), rhs); + } else if (node instanceof org.jrubyparser.ast.ClassVarAsgnNode) { + final org.jrubyparser.ast.ClassVarAsgnNode instAsgnNode = (org.jrubyparser.ast.ClassVarAsgnNode) node; + return new org.jrubyparser.ast.ClassVarAsgnNode(node.getPosition(), instAsgnNode.getName(), rhs); + } else if (node instanceof org.jrubyparser.ast.ConstDeclNode) { + final org.jrubyparser.ast.ConstDeclNode constDeclNode = (org.jrubyparser.ast.ConstDeclNode) node; + return new org.jrubyparser.ast.ConstDeclNode(node.getPosition(), constDeclNode.getName(), (org.jrubyparser.ast.INameNode) constDeclNode.getConstNode(), rhs); + } else { + throw new UnsupportedOperationException("Don't know how to set the RHS of a " + node.getClass().getName()); + } + } + + @Override + public Object visitGlobalAsgnNode(org.jrubyparser.ast.GlobalAsgnNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + final String name = "$" + node.getName(); + final RubyNode rhs = (RubyNode) node.getValue().accept(this); + + if (FRAME_LOCAL_GLOBAL_VARIABLES.contains(name)) { + context.implementationMessage("Assigning to frame local global variables not implemented at %s", node.getPosition()); + + return rhs; + } else { + final ObjectLiteralNode globalVariablesObjectNode = new ObjectLiteralNode(context, sourceSection, context.getCoreLibrary().getGlobalVariablesObject()); + + return new UninitializedWriteInstanceVariableNode(context, sourceSection, name, globalVariablesObjectNode, rhs); + } + } + + @Override + public Object visitGlobalVarNode(org.jrubyparser.ast.GlobalVarNode node) { + final String name = "$" + node.getName(); + final SourceSection sourceSection = translate(node.getPosition()); + + if (FRAME_LOCAL_GLOBAL_VARIABLES.contains(name)) { + // Assignment is implicit for many of these, so we need to declare when we use + + environment.declareVar(name); + + final RubyNode readNode = environment.findLocalVarNode(name, sourceSection); + + return readNode; + } else { + final ObjectLiteralNode globalVariablesObjectNode = new ObjectLiteralNode(context, sourceSection, context.getCoreLibrary().getGlobalVariablesObject()); + + return new UninitializedReadInstanceVariableNode(context, sourceSection, name, globalVariablesObjectNode); + } + } + + @Override + public Object visitHashNode(org.jrubyparser.ast.HashNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + final List keys = new ArrayList<>(); + final List values = new ArrayList<>(); + + final org.jrubyparser.ast.ListNode entries = node.getListNode(); + + assert entries.size() % 2 == 0; + + for (int n = 0; n < entries.size(); n += 2) { + if (entries.get(n) == null) { + final NilNode nilNode = new NilNode(context, sourceSection); + keys.add(nilNode); + } else { + keys.add((RubyNode) entries.get(n).accept(this)); + } + + if (entries.get(n + 1) == null) { + final NilNode nilNode = new NilNode(context, sourceSection); + values.add(nilNode); + } else { + values.add((RubyNode) entries.get(n + 1).accept(this)); + } + } + + return new HashLiteralNode(translate(node.getPosition()), keys.toArray(new RubyNode[keys.size()]), values.toArray(new RubyNode[values.size()]), context); + } + + @Override + public Object visitIfNode(org.jrubyparser.ast.IfNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + org.jrubyparser.ast.Node thenBody = node.getThenBody(); + + if (thenBody == null) { + thenBody = new org.jrubyparser.ast.NilNode(node.getPosition()); + } + + org.jrubyparser.ast.Node elseBody = node.getElseBody(); + + if (elseBody == null) { + elseBody = new org.jrubyparser.ast.NilNode(node.getPosition()); + } + + RubyNode condition; + + if (node.getCondition() == null) { + condition = new NilNode(context, sourceSection); + } else { + condition = (RubyNode) node.getCondition().accept(this); + } + + final BooleanCastNode conditionCast = BooleanCastNodeFactory.create(context, sourceSection, condition); + + final RubyNode thenBodyTranslated = (RubyNode) thenBody.accept(this); + final RubyNode elseBodyTranslated = (RubyNode) elseBody.accept(this); + + return new IfNode(context, sourceSection, conditionCast, thenBodyTranslated, elseBodyTranslated); + } + + @Override + public Object visitInstAsgnNode(org.jrubyparser.ast.InstAsgnNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + final String nameWithoutSigil = node.getName(); + + final RubyNode receiver = new SelfNode(context, sourceSection); + + RubyNode rhs; + + if (node.getValue() == null) { + rhs = new DeadNode(context, sourceSection); + } else { + rhs = (RubyNode) node.getValue().accept(this); + } + + return new UninitializedWriteInstanceVariableNode(context, sourceSection, nameWithoutSigil, receiver, rhs); + } + + @Override + public Object visitInstVarNode(org.jrubyparser.ast.InstVarNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + final String nameWithoutSigil = node.getName(); + + final RubyNode receiver = new SelfNode(context, sourceSection); + + return new UninitializedReadInstanceVariableNode(context, sourceSection, nameWithoutSigil, receiver); + } + + @Override + public Object visitIterNode(org.jrubyparser.ast.IterNode node) { + /* + * In a block we do NOT allocate a new return ID - returns will return from the method, not + * the block (in the general case, see Proc and the difference between Proc and Lambda for + * specifics). + */ + + final boolean hasOwnScope = !translatingForStatement; + + // Unset this flag for any for any blocks within the for statement's body + + translatingForStatement = false; + + final TranslatorEnvironment newEnvironment = new TranslatorEnvironment(context, environment, environment.getParser(), environment.getReturnID(), hasOwnScope, false, + new UniqueMethodIdentifier()); + final MethodTranslator methodCompiler = new MethodTranslator(context, this, newEnvironment, true, source); + + org.jrubyparser.ast.ArgsNode argsNode; + + if (node.getVar() instanceof org.jrubyparser.ast.ArgsNode) { + argsNode = (org.jrubyparser.ast.ArgsNode) node.getVar(); + } else if (node.getVar() instanceof org.jrubyparser.ast.DAsgnNode) { + final org.jrubyparser.ast.ArgumentNode arg = new org.jrubyparser.ast.ArgumentNode(node.getPosition(), ((org.jrubyparser.ast.DAsgnNode) node.getVar()).getName()); + final org.jrubyparser.ast.ListNode preArgs = new org.jrubyparser.ast.ArrayNode(node.getPosition(), arg); + argsNode = new org.jrubyparser.ast.ArgsNode(node.getPosition(), preArgs, null, null, null, null, null, null); + } else if (node.getVar() == null) { + argsNode = null; + } else { + throw new UnsupportedOperationException(); + } + + return methodCompiler.compileFunctionNode(translate(node.getPosition()), "(block)", argsNode, node.getBody()); + } + + @Override + public Object visitLiteralNode(org.jrubyparser.ast.LiteralNode node) { + return unimplemented(node); + } + + @Override + public Object visitLocalAsgnNode(org.jrubyparser.ast.LocalAsgnNode node) { + + final SourceSection sourceSection = translate(node.getPosition()); + + if (environment.getNeverAssignInParentScope()) { + environment.declareVar(node.getName()); + } + + RubyNode lhs = environment.findLocalVarNode(node.getName(), sourceSection); + + if (lhs == null) { + if (environment.hasOwnScopeForAssignments()) { + environment.declareVar(node.getName()); + } + + TranslatorEnvironment environmentToDeclareIn = environment; + + while (!environmentToDeclareIn.hasOwnScopeForAssignments()) { + environmentToDeclareIn = environmentToDeclareIn.getParent(); + } + + environmentToDeclareIn.declareVar(node.getName()); + lhs = environment.findLocalVarNode(node.getName(), sourceSection); + + if (lhs == null) { + throw new RuntimeException("shoudln't be here"); + } + } + + RubyNode rhs; + + if (node.getValue() == null) { + rhs = new DeadNode(context, sourceSection); + } else { + rhs = (RubyNode) node.getValue().accept(this); + } + + RubyNode translated = ((ReadNode) lhs).makeWriteNode(rhs); + + if (context.getConfiguration().getDebug()) { + final UniqueMethodIdentifier methodIdentifier = environment.findMethodForLocalVar(node.getName()); + + RubyProxyNode proxy; + if (translated instanceof RubyProxyNode) { + proxy = (RubyProxyNode) translated; + } else { + proxy = new RubyProxyNode(context, translated); + } + context.getDebugManager().registerLocalDebugProxy(methodIdentifier, node.getName(), proxy.getProbeChain()); + + translated = proxy; + } + + return translated; + } + + @Override + public Object visitLocalVarNode(org.jrubyparser.ast.LocalVarNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + final String name = node.getName(); + + RubyNode readNode = environment.findLocalVarNode(name, sourceSection); + + if (readNode == null) { + context.implementationMessage("Local variable found by parser but not by translator - " + name + " at " + node.getPosition()); + readNode = environment.findLocalVarNode(environment.allocateLocalTemp(), sourceSection); + } + + return readNode; + } + + @Override + public Object visitMatch2Node(org.jrubyparser.ast.Match2Node node) { + final org.jrubyparser.ast.Node argsNode = buildArrayNode(node.getPosition(), node.getValue()); + final org.jrubyparser.ast.Node callNode = new org.jrubyparser.ast.CallNode(node.getPosition(), node.getReceiver(), "=~", argsNode, null); + return callNode.accept(this); + } + + @Override + public Object visitMatch3Node(org.jrubyparser.ast.Match3Node node) { + final org.jrubyparser.ast.Node argsNode = buildArrayNode(node.getPosition(), node.getValue()); + final org.jrubyparser.ast.Node callNode = new org.jrubyparser.ast.CallNode(node.getPosition(), node.getReceiver(), "=~", argsNode, null); + return callNode.accept(this); + } + + @Override + public Object visitMatchNode(org.jrubyparser.ast.MatchNode node) { + return unimplemented(node); + } + + @Override + public Object visitModuleNode(org.jrubyparser.ast.ModuleNode node) { + // See visitClassNode + + final SourceSection sourceSection = translate(node.getPosition()); + + final String name = node.getCPath().getName(); + + final TranslatorEnvironment newEnvironment = new TranslatorEnvironment(context, environment, environment.getParser(), environment.getParser().allocateReturnID(), true, true, + new UniqueMethodIdentifier()); + final ModuleTranslator classTranslator = new ModuleTranslator(context, this, newEnvironment, source); + + final MethodDefinitionNode definitionMethod = classTranslator.compileClassNode(node.getPosition(), node.getCPath().getName(), node.getBody()); + + final DefineOrGetModuleNode defineModuleNode = new DefineOrGetModuleNode(context, sourceSection, name, getModuleToDefineModulesIn(sourceSection)); + + return new OpenModuleNode(context, sourceSection, defineModuleNode, definitionMethod); + } + + @Override + public Object visitMultipleAsgnNode(org.jrubyparser.ast.MultipleAsgnNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + final org.jrubyparser.ast.ArrayNode preArray = (org.jrubyparser.ast.ArrayNode) node.getPre(); + final org.jrubyparser.ast.Node rhs = node.getValue(); + + RubyNode rhsTranslated; + + if (rhs == null) { + context.implementationMessage("warning: no RHS for multiple assignment - using noop"); + rhsTranslated = new NilNode(context, sourceSection); + } else { + rhsTranslated = (RubyNode) rhs.accept(this); + } + + /* + * One very common case is to do + * + * a, b = c, d + */ + + if (preArray != null && node.getPost() == null && node.getRest() == null && rhsTranslated instanceof UninitialisedArrayLiteralNode && + ((UninitialisedArrayLiteralNode) rhsTranslated).getValues().length == preArray.size()) { + /* + * We can deal with this common case be rewriting as + * + * temp1 = c; temp2 = d; a = temp1; b = temp2 + * + * We can't just do + * + * a = c; b = d + * + * As we don't know if d depends on the original value of a. + * + * We also need to return an array [c, d], but we make that result elidable so it isn't + * executed if it isn't actually demanded. + */ + + final RubyNode[] rhsValues = ((UninitialisedArrayLiteralNode) rhsTranslated).getValues(); + final int assignedValuesCount = preArray.size(); + + final RubyNode[] sequence = new RubyNode[assignedValuesCount * 2]; + + final RubyNode[] tempValues = new RubyNode[assignedValuesCount]; + + for (int n = 0; n < assignedValuesCount; n++) { + final String tempName = environment.allocateLocalTemp(); + final RubyNode readTemp = environment.findLocalVarNode(tempName, sourceSection); + final RubyNode assignTemp = ((ReadNode) readTemp).makeWriteNode(rhsValues[n]); + final RubyNode assignFinalValue = translateDummyAssignment(preArray.get(n), readTemp); + + sequence[n] = assignTemp; + sequence[assignedValuesCount + n] = assignFinalValue; + + tempValues[n] = readTemp; + } + + final RubyNode blockNode = new SequenceNode(context, sourceSection, sequence); + + final UninitialisedArrayLiteralNode arrayNode = new UninitialisedArrayLiteralNode(context, sourceSection, tempValues); + + final ElidableResultNode elidableResult = new ElidableResultNode(context, sourceSection, blockNode, arrayNode); + + return elidableResult; + } else if (preArray != null) { + /* + * The other simple case is + * + * a, b, c = x + * + * If x is an array, then it's + * + * a[0] = x[0] etc + * + * If x isn't an array then it's + * + * a, b, c = [x, nil, nil] + * + * Which I believe is the same effect as + * + * a, b, c, = *x + * + * So we insert the splat cast node, even though it isn't there. + */ + + /* + * Create a temp for the array. + */ + + final String tempName = environment.allocateLocalTemp(); + + /* + * Create a sequence of instructions, with the first being the literal array assigned to + * the temp. + */ + + final List sequence = new ArrayList<>(); + + final RubyNode splatCastNode = SplatCastNodeFactory.create(context, sourceSection, rhsTranslated); + + final RubyNode writeTemp = ((ReadNode) environment.findLocalVarNode(tempName, sourceSection)).makeWriteNode(splatCastNode); + + sequence.add(writeTemp); + + /* + * Then index the temp array for each assignment on the LHS. + */ + + for (int n = 0; n < preArray.size(); n++) { + final ArrayIndexNode assignedValue = ArrayIndexNodeFactory.create(context, sourceSection, n, environment.findLocalVarNode(tempName, sourceSection)); + + sequence.add(translateDummyAssignment(preArray.get(n), assignedValue)); + } + + if (node.getRest() != null) { + final ArrayRestNode assignedValue = new ArrayRestNode(context, sourceSection, preArray.size(), environment.findLocalVarNode(tempName, sourceSection)); + + sequence.add(translateDummyAssignment(node.getRest(), assignedValue)); + } + + return new SequenceNode(context, sourceSection, sequence.toArray(new RubyNode[sequence.size()])); + } else if (node.getPre() == null && node.getPost() == null && node.getRest() instanceof org.jrubyparser.ast.StarNode) { + return rhsTranslated; + } else if (node.getPre() == null && node.getPost() == null && node.getRest() != null && rhs != null && !(rhs instanceof org.jrubyparser.ast.ArrayNode)) { + /* + * *a = b + * + * >= 1.8, this seems to be the same as: + * + * a = *b + */ + + final RubyNode restTranslated = ((RubyNode) node.getRest().accept(this)).getNonProxyNode(); + + /* + * Sometimes rest is a corrupt write with no RHS, like in other multiple assignments, + * and sometimes it is already a read. + */ + + ReadNode restRead; + + if (restTranslated instanceof ReadNode) { + restRead = (ReadNode) restTranslated; + } else if (restTranslated instanceof WriteNode) { + restRead = (ReadNode) ((WriteNode) restTranslated).makeReadNode(); + } else { + throw new RuntimeException("Unknown form of multiple assignment " + node + " at " + node.getPosition()); + } + + final SplatCastNode rhsSplatCast = SplatCastNodeFactory.create(context, sourceSection, rhsTranslated); + + return restRead.makeWriteNode(rhsSplatCast); + } else if (node.getPre() == null && node.getPost() == null && node.getRest() != null && rhs != null && rhs instanceof org.jrubyparser.ast.ArrayNode) { + /* + * *a = [b, c] + * + * This seems to be the same as: + * + * a = [b, c] + */ + + final RubyNode restTranslated = ((RubyNode) node.getRest().accept(this)).getNonProxyNode(); + + /* + * Sometimes rest is a corrupt write with no RHS, like in other multiple assignments, + * and sometimes it is already a read. + */ + + ReadNode restRead; + + if (restTranslated instanceof ReadNode) { + restRead = (ReadNode) restTranslated; + } else if (restTranslated instanceof WriteNode) { + restRead = (ReadNode) ((WriteNode) restTranslated).makeReadNode(); + } else { + throw new RuntimeException("Unknown form of multiple assignment " + node + " at " + node.getPosition()); + } + + return restRead.makeWriteNode(rhsTranslated); + } else { + throw new RuntimeException("Unknown form of multiple assignment " + node + " at " + node.getPosition()); + } + } + + private RubyNode translateDummyAssignment(org.jrubyparser.ast.Node dummyAssignment, RubyNode rhs) { + final SourceSection sourceSection = translate(dummyAssignment.getPosition()); + + /* + * This is tricky. To represent the RHS of a multiple assignment they use corrupt assignment + * values, in some cases with no value to be assigned, and in other cases with a dummy + * value. We can't visit them normally, as they're corrupt. We can't just modify them to + * have our RHS, as that's a node in our AST, not theirs. We can't use a dummy value in + * their AST because I can't add new visitors to this interface. + */ + + RubyNode translated; + + if (dummyAssignment instanceof org.jrubyparser.ast.LocalAsgnNode) { + /* + * They have a dummy NilImplicitNode as the RHS. Translate, convert to read, convert to + * write which allows us to set the RHS. + */ + + final WriteNode dummyTranslated = (WriteNode) ((RubyNode) dummyAssignment.accept(this)).getNonProxyNode(); + translated = ((ReadNode) dummyTranslated.makeReadNode()).makeWriteNode(rhs); + } else if (dummyAssignment instanceof org.jrubyparser.ast.InstAsgnNode) { + /* + * Same as before, just a different type of assignment. + */ + + final WriteInstanceVariableNode dummyTranslated = (WriteInstanceVariableNode) dummyAssignment.accept(this); + translated = dummyTranslated.makeReadNode().makeWriteNode(rhs); + } else if (dummyAssignment instanceof org.jrubyparser.ast.AttrAssignNode) { + /* + * They've given us an AttrAssignNode with the final argument, the assigned value, + * missing. If we translate that we'll get foo.[]=(index), so missing the value. To + * solve we have a special version of the visitCallNode that allows us to pass another + * already translated argument, visitCallNodeExtraArgument. However, we initially have + * an AttrAssignNode, so we also need a special version of that. + */ + + final org.jrubyparser.ast.AttrAssignNode dummyAttrAssignment = (org.jrubyparser.ast.AttrAssignNode) dummyAssignment; + translated = visitAttrAssignNodeExtraArgument(dummyAttrAssignment, rhs); + } else if (dummyAssignment instanceof org.jrubyparser.ast.DAsgnNode) { + final RubyNode dummyTranslated = (RubyNode) dummyAssignment.accept(this); + + if (dummyTranslated.getNonProxyNode() instanceof WriteLevelVariableNode) { + translated = ((ReadNode) ((WriteLevelVariableNode) dummyTranslated.getNonProxyNode()).makeReadNode()).makeWriteNode(rhs); + } else { + translated = ((ReadNode) ((WriteLocalVariableNode) dummyTranslated.getNonProxyNode()).makeReadNode()).makeWriteNode(rhs); + } + } else { + translated = ((ReadNode) environment.findLocalVarNode(environment.allocateLocalTemp(), sourceSection)).makeWriteNode(rhs); + } + + return translated; + } + + @Override + public Object visitNewlineNode(org.jrubyparser.ast.NewlineNode node) { + RubyNode translated = (RubyNode) node.getNextNode().accept(this); + + if (context.getConfiguration().getDebug()) { + + RubyProxyNode proxy; + SourceSection sourceSection; + if (translated instanceof RubyProxyNode) { + proxy = (RubyProxyNode) translated; + sourceSection = proxy.getChild().getSourceSection(); + } else { + proxy = new RubyProxyNode(context, translated); + sourceSection = translated.getSourceSection(); + } + context.getDebugManager().registerProbeChain(sourceSection, proxy.getProbeChain()); + translated = proxy; + } + + if (context.getConfiguration().getTrace()) { + RubyProxyNode proxy; + if (translated instanceof RubyProxyNode) { + proxy = (RubyProxyNode) translated; + } else { + proxy = new RubyProxyNode(context, translated); + } + proxy.getProbeChain().appendProbe(new RubyTraceProbe(context)); + + translated = proxy; + } + + return translated; + } + + @Override + public Object visitNextNode(org.jrubyparser.ast.NextNode node) { + return new NextNode(context, translate(node.getPosition())); + } + + @Override + public Object visitNilNode(org.jrubyparser.ast.NilNode node) { + return new NilNode(context, translate(node.getPosition())); + } + + @Override + public Object visitNotNode(org.jrubyparser.ast.NotNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + final BooleanCastNode booleanCastNode = BooleanCastNodeFactory.create(context, sourceSection, (RubyNode) node.getCondition().accept(this)); + + return new NotNode(context, sourceSection, booleanCastNode); + } + + @Override + public Object visitNthRefNode(org.jrubyparser.ast.NthRefNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + final String name = "$" + node.getMatchNumber(); + + RubyNode readLocal = environment.findLocalVarNode(name, sourceSection); + + if (readLocal == null) { + environment.declareVar(name); + readLocal = environment.findLocalVarNode(name, sourceSection); + } + + return readLocal; + } + + @Override + public Object visitOpAsgnAndNode(org.jrubyparser.ast.OpAsgnAndNode node) { + final org.jrubyparser.ast.Node lhs = node.getFirst(); + final org.jrubyparser.ast.Node rhs = node.getSecond(); + + return AndNodeFactory.create(context, translate(node.getPosition()), (RubyNode) lhs.accept(this), (RubyNode) rhs.accept(this)); + } + + @Override + public Object visitOpAsgnNode(org.jrubyparser.ast.OpAsgnNode node) { + /* + * We're going to de-sugar a.foo += c into a.foo = a.foo + c. Note that we can't evaluate a + * more than once, so we put it into a temporary, and we're doing something more like: + * + * temp = a; temp.foo = temp.foo + c + */ + + final String temp = environment.allocateLocalTemp(); + final org.jrubyparser.ast.Node writeReceiverToTemp = new org.jrubyparser.ast.LocalAsgnNode(node.getPosition(), temp, 0, node.getReceiver()); + final org.jrubyparser.ast.Node readReceiverFromTemp = new org.jrubyparser.ast.LocalVarNode(node.getPosition(), 0, temp); + + final org.jrubyparser.ast.Node readMethod = new org.jrubyparser.ast.CallNode(node.getPosition(), readReceiverFromTemp, node.getVariableName(), null); + final org.jrubyparser.ast.Node operation = new org.jrubyparser.ast.CallNode(node.getPosition(), readMethod, node.getOperatorName(), buildArrayNode(node.getPosition(), node.getValue())); + final org.jrubyparser.ast.Node writeMethod = new org.jrubyparser.ast.CallNode(node.getPosition(), readReceiverFromTemp, node.getVariableName() + "=", buildArrayNode(node.getPosition(), + operation)); + + final org.jrubyparser.ast.BlockNode block = new org.jrubyparser.ast.BlockNode(node.getPosition()); + block.add(writeReceiverToTemp); + block.add(writeMethod); + + return block.accept(this); + } + + @Override + public Object visitOpAsgnOrNode(org.jrubyparser.ast.OpAsgnOrNode node) { + /* + * De-sugar x ||= y into x || x = y. No repeated evaluations there so it's easy. It's also + * basically how jruby-parser represents it already. We'll do it directly, rather than via + * another JRuby AST node. + */ + + final org.jrubyparser.ast.Node lhs = node.getFirst(); + final org.jrubyparser.ast.Node rhs = node.getSecond(); + + return OrNodeFactory.create(context, translate(node.getPosition()), (RubyNode) lhs.accept(this), (RubyNode) rhs.accept(this)); + } + + @Override + public Object visitOpElementAsgnNode(org.jrubyparser.ast.OpElementAsgnNode node) { + /* + * We're going to de-sugar a[b] += c into a[b] = a[b] + c. See discussion in + * visitOpAsgnNode. + */ + + org.jrubyparser.ast.Node index; + + if (node.getArgs() == null) { + index = null; + } else { + index = node.getArgs().childNodes().get(0); + } + + final org.jrubyparser.ast.Node operand = node.getValue(); + + final String temp = environment.allocateLocalTemp(); + final org.jrubyparser.ast.Node writeArrayToTemp = new org.jrubyparser.ast.LocalAsgnNode(node.getPosition(), temp, 0, node.getReceiver()); + final org.jrubyparser.ast.Node readArrayFromTemp = new org.jrubyparser.ast.LocalVarNode(node.getPosition(), 0, temp); + + final org.jrubyparser.ast.Node arrayRead = new org.jrubyparser.ast.CallNode(node.getPosition(), readArrayFromTemp, "[]", buildArrayNode(node.getPosition(), index)); + + final String op = node.getOperatorName(); + + org.jrubyparser.ast.Node operation = null; + + if (op.equals("||")) { + operation = new org.jrubyparser.ast.OrNode(node.getPosition(), arrayRead, operand); + } else if (op.equals("&&")) { + operation = new org.jrubyparser.ast.AndNode(node.getPosition(), arrayRead, operand); + } else { + operation = new org.jrubyparser.ast.CallNode(node.getPosition(), arrayRead, node.getOperatorName(), buildArrayNode(node.getPosition(), operand)); + } + + final org.jrubyparser.ast.Node arrayWrite = new org.jrubyparser.ast.CallNode(node.getPosition(), readArrayFromTemp, "[]=", buildArrayNode(node.getPosition(), index, operation)); + + final org.jrubyparser.ast.BlockNode block = new org.jrubyparser.ast.BlockNode(node.getPosition()); + block.add(writeArrayToTemp); + block.add(arrayWrite); + + return block.accept(this); + } + + private static org.jrubyparser.ast.ArrayNode buildArrayNode(org.jrubyparser.SourcePosition sourcePosition, org.jrubyparser.ast.Node first, org.jrubyparser.ast.Node... rest) { + if (first == null) { + return new org.jrubyparser.ast.ArrayNode(sourcePosition); + } + + final org.jrubyparser.ast.ArrayNode array = new org.jrubyparser.ast.ArrayNode(sourcePosition, first); + + for (org.jrubyparser.ast.Node node : rest) { + array.add(node); + } + + return array; + } + + @Override + public Object visitOrNode(org.jrubyparser.ast.OrNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + RubyNode x; + + if (node.getFirst() == null) { + x = new NilNode(context, sourceSection); + } else { + x = (RubyNode) node.getFirst().accept(this); + } + + RubyNode y; + + if (node.getSecond() == null) { + y = new NilNode(context, sourceSection); + } else { + y = (RubyNode) node.getSecond().accept(this); + } + + return OrNodeFactory.create(context, sourceSection, x, y); + } + + @Override + public Object visitPostExeNode(org.jrubyparser.ast.PostExeNode node) { + return unimplemented(node); + } + + @Override + public Object visitPreExeNode(org.jrubyparser.ast.PreExeNode node) { + return unimplemented(node); + } + + @Override + public Object visitRedoNode(org.jrubyparser.ast.RedoNode node) { + return new RedoNode(context, translate(node.getPosition())); + } + + @Override + public Object visitRegexpNode(org.jrubyparser.ast.RegexpNode node) { + RubyRegexp regexp; + + try { + final String patternText = node.getValue(); + + int flags = Pattern.MULTILINE | Pattern.UNIX_LINES; + + final org.jrubyparser.RegexpOptions options = node.getOptions(); + + if (options.isIgnorecase()) { + flags |= Pattern.CASE_INSENSITIVE; + } + + if (options.isMultiline()) { + // TODO(cs): isn't this the default? + flags |= Pattern.MULTILINE; + } + + final Pattern pattern = Pattern.compile(patternText, flags); + + regexp = new RubyRegexp(context.getCoreLibrary().getRegexpClass(), pattern); + } catch (PatternSyntaxException e) { + context.implementationMessage("failed to parse Ruby regexp " + node.getValue() + " as Java regexp - replacing with ."); + regexp = new RubyRegexp(context.getCoreLibrary().getRegexpClass(), "."); + } + + final ObjectLiteralNode literalNode = new ObjectLiteralNode(context, translate(node.getPosition()), regexp); + return literalNode; + } + + @Override + public Object visitRescueBodyNode(org.jrubyparser.ast.RescueBodyNode node) { + return unimplemented(node); + } + + @Override + public Object visitRescueNode(org.jrubyparser.ast.RescueNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + RubyNode tryPart; + + if (node.getBody() != null) { + tryPart = (RubyNode) node.getBody().accept(this); + } else { + tryPart = new NilNode(context, sourceSection); + } + + final List rescueNodes = new ArrayList<>(); + + org.jrubyparser.ast.RescueBodyNode rescueBody = node.getRescue(); + + while (rescueBody != null) { + if (rescueBody.getExceptions() != null) { + if (rescueBody.getExceptions() instanceof org.jrubyparser.ast.ArrayNode) { + final List exceptionNodes = ((org.jrubyparser.ast.ArrayNode) rescueBody.getExceptions()).childNodes(); + + final RubyNode[] handlingClasses = new RubyNode[exceptionNodes.size()]; + + for (int n = 0; n < handlingClasses.length; n++) { + handlingClasses[n] = (RubyNode) exceptionNodes.get(n).accept(this); + } + + RubyNode translatedBody; + + if (rescueBody.getBody() == null) { + translatedBody = new NilNode(context, sourceSection); + } else { + translatedBody = (RubyNode) rescueBody.getBody().accept(this); + } + + final RescueClassesNode rescueNode = new RescueClassesNode(context, sourceSection, handlingClasses, translatedBody); + rescueNodes.add(rescueNode); + } else if (rescueBody.getExceptions() instanceof org.jrubyparser.ast.SplatNode) { + final org.jrubyparser.ast.SplatNode splat = (org.jrubyparser.ast.SplatNode) rescueBody.getExceptions(); + + RubyNode splatTranslated; + + if (splat.getValue() == null) { + splatTranslated = new NilNode(context, sourceSection); + } else { + splatTranslated = (RubyNode) splat.getValue().accept(this); + } + + RubyNode bodyTranslated; + + if (rescueBody.getBody() == null) { + bodyTranslated = new NilNode(context, sourceSection); + } else { + bodyTranslated = (RubyNode) rescueBody.getBody().accept(this); + } + + final RescueSplatNode rescueNode = new RescueSplatNode(context, sourceSection, splatTranslated, bodyTranslated); + rescueNodes.add(rescueNode); + } else { + unimplemented(node); + } + } else { + RubyNode bodyNode; + + if (rescueBody.getBody() == null) { + bodyNode = new NilNode(context, sourceSection); + } else { + bodyNode = (RubyNode) rescueBody.getBody().accept(this); + } + + final RescueAnyNode rescueNode = new RescueAnyNode(context, sourceSection, bodyNode); + rescueNodes.add(rescueNode); + } + + rescueBody = rescueBody.getOptRescue(); + } + + RubyNode elsePart; + + if (node.getElse() != null) { + elsePart = (RubyNode) node.getElse().accept(this); + } else { + elsePart = new NilNode(context, sourceSection); + } + + return new TryNode(context, sourceSection, tryPart, rescueNodes.toArray(new RescueNode[rescueNodes.size()]), elsePart); + } + + @Override + public Object visitRestArgNode(org.jrubyparser.ast.RestArgNode node) { + return unimplemented(node); + } + + @Override + public Object visitRetryNode(org.jrubyparser.ast.RetryNode node) { + return new RetryNode(context, translate(node.getPosition())); + } + + @Override + public Object visitReturnNode(org.jrubyparser.ast.ReturnNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + RubyNode translatedChild; + + if (node.getValue() == null) { + translatedChild = new NilNode(context, sourceSection); + } else { + translatedChild = (RubyNode) node.getValue().accept(this); + } + + return new ReturnNode(context, sourceSection, environment.getReturnID(), translatedChild); + } + + @Override + public Object visitRootNode(org.jrubyparser.ast.RootNode node) { + return unimplemented(node); + } + + @Override + public Object visitSClassNode(org.jrubyparser.ast.SClassNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + final TranslatorEnvironment newEnvironment = new TranslatorEnvironment(context, environment, environment.getParser(), environment.getParser().allocateReturnID(), true, true, + new UniqueMethodIdentifier()); + final ModuleTranslator classTranslator = new ModuleTranslator(context, this, newEnvironment, source); + + final MethodDefinitionNode definitionMethod = classTranslator.compileClassNode(node.getPosition(), "singleton", node.getBody()); + + final RubyNode receiverNode = (RubyNode) node.getReceiver().accept(this); + + final SingletonClassNode singletonClassNode = new SingletonClassNode(context, sourceSection, receiverNode); + + return new OpenModuleNode(context, sourceSection, singletonClassNode, definitionMethod); + } + + @Override + public Object visitSValueNode(org.jrubyparser.ast.SValueNode node) { + return node.getValue().accept(this); + } + + @Override + public Object visitSelfNode(org.jrubyparser.ast.SelfNode node) { + return new SelfNode(context, translate(node.getPosition())); + } + + @Override + public Object visitSplatNode(org.jrubyparser.ast.SplatNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + RubyNode value; + + if (node.getValue() == null) { + value = new NilNode(context, sourceSection); + } else { + value = (RubyNode) node.getValue().accept(this); + } + + return SplatCastNodeFactory.create(context, sourceSection, value); + } + + @Override + public Object visitStrNode(org.jrubyparser.ast.StrNode node) { + return new StringLiteralNode(context, translate(node.getPosition()), node.getValue()); + } + + @Override + public Object visitSuperNode(org.jrubyparser.ast.SuperNode node) { + return unimplemented(node); + } + + @Override + public Object visitSymbolNode(org.jrubyparser.ast.SymbolNode node) { + return new ObjectLiteralNode(context, translate(node.getPosition()), new RubySymbol(context.getCoreLibrary().getSymbolClass(), node.getName())); + } + + @Override + public Object visitToAryNode(org.jrubyparser.ast.ToAryNode node) { + return unimplemented(node); + } + + @Override + public Object visitTrueNode(org.jrubyparser.ast.TrueNode node) { + return new BooleanLiteralNode(context, translate(node.getPosition()), true); + } + + @Override + public Object visitUndefNode(org.jrubyparser.ast.UndefNode node) { + return unimplemented(node); + } + + @Override + public Object visitUntilNode(org.jrubyparser.ast.UntilNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + RubyNode condition; + + if (node.getCondition() == null) { + condition = new NilNode(context, sourceSection); + } else { + condition = (RubyNode) node.getCondition().accept(this); + } + + final BooleanCastNode conditionCast = BooleanCastNodeFactory.create(context, sourceSection, condition); + final NotNode conditionCastNot = new NotNode(context, sourceSection, conditionCast); + final BooleanCastNode conditionCastNotCast = BooleanCastNodeFactory.create(context, sourceSection, conditionCastNot); + + final RubyNode body = (RubyNode) node.getBody().accept(this); + + return new WhileNode(context, sourceSection, conditionCastNotCast, body); + } + + @Override + public Object visitVAliasNode(org.jrubyparser.ast.VAliasNode node) { + return unimplemented(node); + } + + @Override + public Object visitVCallNode(org.jrubyparser.ast.VCallNode node) { + final org.jrubyparser.ast.Node receiver = new org.jrubyparser.ast.SelfNode(node.getPosition()); + final org.jrubyparser.ast.Node args = null; + final org.jrubyparser.ast.Node callNode = new org.jrubyparser.ast.CallNode(node.getPosition(), receiver, node.getName(), args); + + return callNode.accept(this); + } + + @Override + public Object visitWhenNode(org.jrubyparser.ast.WhenNode node) { + return unimplemented(node); + } + + @Override + public Object visitWhileNode(org.jrubyparser.ast.WhileNode node) { + final SourceSection sourceSection = translate(node.getPosition()); + + RubyNode condition; + + if (node.getCondition() == null) { + condition = new NilNode(context, sourceSection); + } else { + condition = (RubyNode) node.getCondition().accept(this); + } + + final BooleanCastNode conditionCast = BooleanCastNodeFactory.create(context, sourceSection, condition); + + final RubyNode body = (RubyNode) node.getBody().accept(this); + + return new WhileNode(context, sourceSection, conditionCast, body); + } + + @Override + public Object visitXStrNode(org.jrubyparser.ast.XStrNode node) { + SourceSection sourceSection = translate(node.getPosition()); + + final StringLiteralNode literal = new StringLiteralNode(context, sourceSection, node.getValue()); + + return new SystemNode(context, sourceSection, literal); + } + + @Override + public Object visitYieldNode(org.jrubyparser.ast.YieldNode node) { + final List arguments = new ArrayList<>(); + + final org.jrubyparser.ast.Node argsNode = node.getArgs(); + + if (argsNode != null) { + if (argsNode instanceof org.jrubyparser.ast.ListNode) { + arguments.addAll(((org.jrubyparser.ast.ListNode) node.getArgs()).childNodes()); + } else { + arguments.add(node.getArgs()); + } + } + + final List argumentsTranslated = new ArrayList<>(); + + for (org.jrubyparser.ast.Node argument : arguments) { + argumentsTranslated.add((RubyNode) argument.accept(this)); + } + + final RubyNode[] argumentsTranslatedArray = argumentsTranslated.toArray(new RubyNode[argumentsTranslated.size()]); + + return new YieldNode(context, translate(node.getPosition()), argumentsTranslatedArray); + } + + @Override + public Object visitZArrayNode(org.jrubyparser.ast.ZArrayNode node) { + final RubyNode[] values = new RubyNode[0]; + + return new UninitialisedArrayLiteralNode(context, translate(node.getPosition()), values); + } + + @Override + public Object visitZSuperNode(org.jrubyparser.ast.ZSuperNode node) { + return unimplemented(node); + } + + public Object visitArgumentNode(org.jrubyparser.ast.ArgumentNode node) { + return unimplemented(node); + } + + public Object visitCommentNode(org.jrubyparser.ast.CommentNode node) { + return unimplemented(node); + } + + public Object visitKeywordArgNode(org.jrubyparser.ast.KeywordArgNode node) { + return unimplemented(node); + } + + public Object visitKeywordRestArgNode(org.jrubyparser.ast.KeywordRestArgNode node) { + return unimplemented(node); + } + + public Object visitListNode(org.jrubyparser.ast.ListNode node) { + return unimplemented(node); + } + + public Object visitMethodNameNode(org.jrubyparser.ast.MethodNameNode node) { + return unimplemented(node); + } + + public Object visitOptArgNode(org.jrubyparser.ast.OptArgNode node) { + return unimplemented(node); + } + + public Object visitSyntaxNode(org.jrubyparser.ast.SyntaxNode node) { + return unimplemented(node); + } + + public Object visitImplicitNilNode(org.jrubyparser.ast.ImplicitNilNode node) { + return new NilNode(context, translate(node.getPosition())); + } + + public Object visitLambdaNode(org.jrubyparser.ast.LambdaNode node) { + // TODO(cs): code copied and modified from visitIterNode - extract common + + final TranslatorEnvironment newEnvironment = new TranslatorEnvironment(context, environment, environment.getParser(), environment.getReturnID(), false, false, new UniqueMethodIdentifier()); + final MethodTranslator methodCompiler = new MethodTranslator(context, this, newEnvironment, false, source); + + org.jrubyparser.ast.ArgsNode argsNode; + + if (node.getVar() instanceof org.jrubyparser.ast.ArgsNode) { + argsNode = (org.jrubyparser.ast.ArgsNode) node.getVar(); + } else if (node.getVar() instanceof org.jrubyparser.ast.DAsgnNode) { + final org.jrubyparser.ast.ArgumentNode arg = new org.jrubyparser.ast.ArgumentNode(node.getPosition(), ((org.jrubyparser.ast.DAsgnNode) node.getVar()).getName()); + final org.jrubyparser.ast.ListNode preArgs = new org.jrubyparser.ast.ArrayNode(node.getPosition(), arg); + argsNode = new org.jrubyparser.ast.ArgsNode(node.getPosition(), preArgs, null, null, null, null, null, null); + } else if (node.getVar() == null) { + argsNode = null; + } else { + throw new UnsupportedOperationException(); + } + + final MethodDefinitionNode definitionNode = methodCompiler.compileFunctionNode(translate(node.getPosition()), "(lambda)", argsNode, node.getBody()); + + return new LambdaNode(context, translate(node.getPosition()), definitionNode); + } + + public Object visitUnaryCallNode(org.jrubyparser.ast.UnaryCallNode node) { + final org.jrubyparser.ast.Node callNode = new org.jrubyparser.ast.CallNode(node.getPosition(), node.getReceiver(), node.getName(), null, null); + return callNode.accept(this); + } + + protected Object unimplemented(org.jrubyparser.ast.Node node) { + context.implementationMessage("warning: %s at %s does nothing", node, node.getPosition()); + return new NilNode(context, translate(node.getPosition())); + } + + protected SourceSection translate(final org.jrubyparser.SourcePosition sourcePosition) { + try { + // TODO(cs): get an identifier + final String identifier = "(identifier)"; + + // TODO(cs): work out the start column + final int startColumn = -1; + + final int charLength = sourcePosition.getEndOffset() - sourcePosition.getStartOffset(); + + return new DefaultSourceSection(source, identifier, sourcePosition.getStartLine() + 1, startColumn, sourcePosition.getStartOffset(), charLength); + } catch (UnsupportedOperationException e) { + // In some circumstances JRuby can't tell you what the position is + return translate(new org.jrubyparser.SourcePosition("(unknown)", 0, 0)); + } + } + + protected SequenceNode initFlipFlopStates(SourceSection sourceSection) { + final RubyNode[] initNodes = new RubyNode[environment.getFlipFlopStates().size()]; + + for (int n = 0; n < initNodes.length; n++) { + initNodes[n] = new InitFlipFlopSlotNode(context, sourceSection, environment.getFlipFlopStates().get(n)); + } + + return new SequenceNode(context, sourceSection, initNodes); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/TranslatorEnvironment.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.parser/src/com/oracle/truffle/ruby/parser/TranslatorEnvironment.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.parser; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.nodes.*; +import com.oracle.truffle.ruby.nodes.methods.locals.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +public class TranslatorEnvironment { + + private final RubyContext context; + + private final FrameDescriptor frameDescriptor; + + private final List preParameters = new ArrayList<>(); + + private final List optionalParameters = new ArrayList<>(); + private final Map optionalParametersDefaultValues = new HashMap<>(); + + private final List postParameters = new ArrayList<>(); + + private final List flipFlopStates = new ArrayList<>(); + + private FrameSlot restParameter = null; + + private FrameSlot blockParameter = null; + + private JRubyParser parser; + private final long returnID; + + private final boolean ownScopeForAssignments; + private final boolean neverAssignInParentScope; + + protected final TranslatorEnvironment parent; + private String methodName = ""; + private boolean needsDeclarationFrame = false; + private UniqueMethodIdentifier methodIdentifier; + + private int tempIndex; + + public TranslatorEnvironment(RubyContext context, TranslatorEnvironment parent, FrameDescriptor frameDescriptor, JRubyParser parser, long returnID, boolean ownScopeForAssignments, + boolean neverAssignInParentScope, UniqueMethodIdentifier methodIdentifier) { + this.context = context; + this.parent = parent; + this.frameDescriptor = frameDescriptor; + this.parser = parser; + this.returnID = returnID; + this.ownScopeForAssignments = ownScopeForAssignments; + this.neverAssignInParentScope = neverAssignInParentScope; + this.methodIdentifier = methodIdentifier; + } + + public TranslatorEnvironment(RubyContext context, TranslatorEnvironment parent, JRubyParser parser, long returnID, boolean ownScopeForAssignments, boolean neverAssignInParentScope, + UniqueMethodIdentifier methodIdentifier) { + this(context, parent, new FrameDescriptor(RubyFrameTypeConversion.getInstance()), parser, returnID, ownScopeForAssignments, neverAssignInParentScope, methodIdentifier); + } + + public int getLocalVarCount() { + return getFrameDescriptor().getSize(); + } + + public TranslatorEnvironment getParent() { + return parent; + } + + public List getPreParameters() { + return preParameters; + } + + public List getOptionalParameters() { + return optionalParameters; + } + + public Map getOptionalParametersDefaultValues() { + return optionalParametersDefaultValues; + } + + public List getPostParameters() { + return postParameters; + } + + public TranslatorEnvironment getParent(int level) { + assert level >= 0; + if (level == 0) { + return this; + } else { + return parent.getParent(level - 1); + } + } + + public FrameSlot declareVar(String name) { + return getFrameDescriptor().findOrAddFrameSlot(name); + } + + public UniqueMethodIdentifier findMethodForLocalVar(String name) { + TranslatorEnvironment current = this; + do { + FrameSlot slot = current.getFrameDescriptor().findFrameSlot(name); + if (slot != null) { + return current.methodIdentifier; + } + + current = current.parent; + } while (current != null); + + return null; + } + + public RubyNode findLocalVarNode(String name, SourceSection sourceSection) { + TranslatorEnvironment current = this; + int level = -1; + try { + do { + level++; + FrameSlot slot = current.getFrameDescriptor().findFrameSlot(name); + if (slot != null) { + if (level == 0) { + return ReadLocalVariableNodeFactory.create(context, sourceSection, slot); + } else { + return ReadLevelVariableNodeFactory.create(context, sourceSection, slot, level); + } + } + + current = current.parent; + } while (current != null); + } finally { + if (current != null) { + current = this; + while (level-- > 0) { + current.needsDeclarationFrame = true; + current = current.parent; + } + } + } + + return null; + } + + public void setRestParameter(FrameSlot restParameter) { + this.restParameter = restParameter; + } + + public FrameSlot getRestParameter() { + return restParameter; + } + + public void setBlockParameter(FrameSlot blockParameter) { + this.blockParameter = blockParameter; + } + + public FrameSlot getBlockParameter() { + return blockParameter; + } + + public void declareFunction(String name) { + declareVar(name); + } + + public String getMethodName() { + return methodName; + } + + public void setMethodName(String methodName) { + this.methodName = methodName; + } + + public void setNeedsDeclarationFrame() { + needsDeclarationFrame = true; + } + + public boolean needsDeclarationFrame() { + return needsDeclarationFrame; + } + + public FrameDescriptor getFrameDescriptor() { + return frameDescriptor; + } + + public String allocateLocalTemp() { + final String name = "rubytruffle_temp" + tempIndex; + tempIndex++; + declareVar(name); + return name; + } + + public long getReturnID() { + return returnID; + } + + public JRubyParser getParser() { + return parser; + } + + public boolean hasOwnScopeForAssignments() { + return ownScopeForAssignments; + } + + public boolean getNeverAssignInParentScope() { + return neverAssignInParentScope; + } + + public void addMethodDeclarationSlots() { + frameDescriptor.addFrameSlot(RubyModule.VISIBILITY_FRAME_SLOT_ID); + frameDescriptor.addFrameSlot(RubyModule.MODULE_FUNCTION_FLAG_FRAME_SLOT_ID); + } + + public UniqueMethodIdentifier getUniqueMethodIdentifier() { + return methodIdentifier; + } + + public List getFlipFlopStates() { + return flipFlopStates; + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/.checkstyle_checks.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/.checkstyle_checks.xml Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/InputReader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/InputReader.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime; + +import java.io.*; + +/** + * Interface allowing Ruby {@code Kernel#gets} to be configured to use the standard Java readLine, + * some library like JLine, or to be mocked for testing. + */ +public interface InputReader { + + /** + * Show a prompt and read one line of input. + */ + String readLine(String prompt) throws IOException; + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/NilPlaceholder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/NilPlaceholder.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime; + +/** + * Represents the Ruby {@code Nil} object, but without being a full Ruby object. This allows us to + * have a simple values that is {@code nil}, but more readily available than the particular instance + * for a context. + */ +public final class NilPlaceholder { + + public static final NilPlaceholder INSTANCE = new NilPlaceholder(); + + private NilPlaceholder() { + } + + @Override + public String toString() { + return ""; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyArguments.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyArguments.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * Arguments and other context passed to a Ruby method. Includes the central Ruby context object, + * optionally the scope at the point of declaration (forming a closure), the value of self, a passed + * block, and the formal arguments. + */ +public final class RubyArguments extends Arguments { + + private final MaterializedFrame declarationFrame; + private final Object self; + private final RubyProc block; + private final Object[] arguments; + + public RubyArguments(MaterializedFrame declarationFrame, Object self, RubyProc block, Object... arguments) { + assert self != null; + assert arguments != null; + + this.declarationFrame = declarationFrame; + this.self = self; + this.block = block; + this.arguments = arguments; + } + + public MaterializedFrame getDeclarationFrame() { + return declarationFrame; + } + + /** + * Get the declaration frame a certain number of levels up from the current frame, where the + * current frame is 0. + */ + public static MaterializedFrame getDeclarationFrame(VirtualFrame frame, int level) { + assert level > 0; + + MaterializedFrame parentFrame = frame.getArguments(RubyArguments.class).getDeclarationFrame(); + return getDeclarationFrame(parentFrame, level - 1); + } + + /** + * Get the declaration frame a certain number of levels up from the current frame, where the + * current frame is 0. + */ + @ExplodeLoop + private static MaterializedFrame getDeclarationFrame(MaterializedFrame frame, int level) { + assert frame != null; + assert level >= 0; + + MaterializedFrame parentFrame = frame; + + for (int n = 0; n < level; n++) { + parentFrame = parentFrame.getArguments(RubyArguments.class).getDeclarationFrame(); + } + + return parentFrame; + } + + public Object getSelf() { + return self; + } + + public RubyProc getBlock() { + return block; + } + + public Object[] getArguments() { + return arguments; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyContext.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyContext.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime; + +import java.math.*; +import java.util.concurrent.atomic.*; + +import jnr.posix.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.source.*; +import com.oracle.truffle.ruby.runtime.configuration.*; +import com.oracle.truffle.ruby.runtime.control.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.debug.*; +import com.oracle.truffle.ruby.runtime.methods.*; +import com.oracle.truffle.ruby.runtime.objects.*; +import com.oracle.truffle.ruby.runtime.subsystems.*; + +/** + * The global state of a running Ruby system. + */ +public class RubyContext implements ExecutionContext { + + private final Configuration configuration; + private final RubyParser parser; + private final CoreLibrary coreLibrary; + private final FeatureManager featureManager; + private final ObjectSpaceManager objectSpaceManager; + private final TraceManager traceManager; + private final ThreadManager threadManager; + private final FiberManager fiberManager; + private final AtExitManager atExitManager; + private final RubyDebugManager debugManager; + private final SourceManager sourceManager; + + private AtomicLong nextObjectID = new AtomicLong(0); + + private String currentDirectory = System.getProperty("user.dir"); + + private POSIX posix = POSIXFactory.getPOSIX(); + + public RubyContext(RubyParser parser) { + this(new Configuration(new ConfigurationBuilder()), parser); + } + + public RubyContext(Configuration configuration, RubyParser parser) { + assert configuration != null; + + this.configuration = configuration; + this.parser = parser; + + objectSpaceManager = new ObjectSpaceManager(this); + traceManager = new TraceManager(this); + + // See note in CoreLibrary#initialize to see why we need to break this into two statements + coreLibrary = new CoreLibrary(this); + coreLibrary.initialize(); + + featureManager = new FeatureManager(this); + atExitManager = new AtExitManager(); + sourceManager = new SourceManager(); + + debugManager = configuration.getDebug() ? new RubyDebugManager(this) : null; + + // Must initialize threads before fibers + + threadManager = new ThreadManager(this); + + if (configuration.getRubyVersion().is19OrLater()) { + fiberManager = new FiberManager(this); + } else { + fiberManager = null; + } + } + + public String getLanguageShortName() { + return configuration.getRubyVersion().getShortName(); + } + + public RubyDebugManager getDebugManager() { + return debugManager; + } + + public void implementationMessage(String format, Object... arguments) { + System.err.println("rubytruffle: " + String.format(format, arguments)); + } + + public void load(Source source) { + execute(this, source, RubyParser.ParserContext.TOP_LEVEL, coreLibrary.getMainObject(), null); + } + + public void loadFile(String fileName) { + final Source source = sourceManager.get(fileName); + final String code = source.getCode(); + if (code == null) { + throw new RuntimeException("Can't read file " + fileName); + } + execute(this, source, RubyParser.ParserContext.TOP_LEVEL, coreLibrary.getMainObject(), null); + } + + /** + * Receives runtime notification that execution has halted. + */ + public void haltedAt(Node node, MaterializedFrame frame) { + runShell(node, frame); + } + + public Object eval(String code) { + final Source source = sourceManager.get("(eval)", code); + return execute(this, source, RubyParser.ParserContext.TOP_LEVEL, coreLibrary.getMainObject(), null); + } + + public Object eval(String code, RubyModule module) { + final Source source = sourceManager.get("(eval)", code); + return execute(this, source, RubyParser.ParserContext.MODULE, module, null); + } + + public Object eval(String code, RubyBinding binding) { + final Source source = sourceManager.get("(eval)", code); + return execute(this, source, RubyParser.ParserContext.TOP_LEVEL, binding.getSelf(), binding.getFrame()); + } + + public void runShell(Node node, MaterializedFrame frame) { + MaterializedFrame existingLocals = frame; + + String prompt = "Ruby> "; + if (node != null) { + final SourceSection src = node.getSourceSection(); + if (src != null) { + prompt = (src.getSource().getName() + ":" + src.getStartLine() + "> "); + } + } + + while (true) { + try { + final String line = configuration.getInputReader().readLine(prompt); + + final ShellResult result = evalShell(line, existingLocals); + + configuration.getStandardOut().println("=> " + result.getResult()); + + existingLocals = result.getFrame(); + } catch (BreakShellException e) { + return; + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public ShellResult evalShell(String code, MaterializedFrame existingLocals) { + final Source source = sourceManager.get("(shell)", code); + return (ShellResult) execute(this, source, RubyParser.ParserContext.SHELL, coreLibrary.getMainObject(), existingLocals); + } + + public Object execute(RubyContext context, Source source, RubyParser.ParserContext parserContext, Object self, MaterializedFrame parentFrame) { + if (configuration.getPrintExecutedFiles()) { + implementationMessage("executing: %s", source.getName()); + } + + try { + final RubyParserResult parseResult = parser.parse(context, source, parserContext, parentFrame); + final RubyArguments arguments = new RubyArguments(parentFrame, self, null); + final CallTarget callTarget = Truffle.getRuntime().createCallTarget(parseResult.getRootNode(), parseResult.getFrameDescriptor()); + + return callTarget.call(null, arguments); + } catch (RaiseException e) { + throw e; + } catch (ThrowException e) { + if (context.getConfiguration().getRubyVersion().is18OrEarlier()) { + throw new RaiseException(context.getCoreLibrary().nameErrorUncaughtThrow(e.getTag())); + } else { + throw new RaiseException(context.getCoreLibrary().argumentErrorUncaughtThrow(e.getTag())); + } + } catch (BreakShellException | QuitException e) { + throw e; + } catch (Throwable e) { + throw new RaiseException(ExceptionTranslator.translateException(this, e)); + } + } + + public long getNextObjectID() { + // TODO(CS): We can theoretically run out of long values + + final long id = nextObjectID.getAndIncrement(); + + if (id < 0) { + nextObjectID.set(Long.MIN_VALUE); + throw new RuntimeException("Object IDs exhausted"); + } + + return id; + } + + public void shutdown() { + atExitManager.run(); + + threadManager.leaveGlobalLock(); + + objectSpaceManager.shutdown(); + + if (fiberManager != null) { + fiberManager.shutdown(); + } + } + + public RubyString makeString(String string) { + return new RubyString(coreLibrary.getStringClass(), string); + } + + public RubyString makeString(char string) { + return makeString(Character.toString(string)); + } + + public Configuration getConfiguration() { + return configuration; + } + + public CoreLibrary getCoreLibrary() { + return coreLibrary; + } + + public FeatureManager getFeatureManager() { + return featureManager; + } + + public ObjectSpaceManager getObjectSpaceManager() { + return objectSpaceManager; + } + + public TraceManager getTraceManager() { + return traceManager; + } + + public FiberManager getFiberManager() { + return fiberManager; + } + + public ThreadManager getThreadManager() { + return threadManager; + } + + public RubyParser getParser() { + return parser; + } + + /** + * Utility method to check if an object should be visible in a Ruby program. Used in assertions + * at method boundaries to check that only values we want to be visible to the programmer become + * so. + */ + public static boolean shouldObjectBeVisible(Object object) { + // TODO(cs): RubyMethod should never be visible + + return object instanceof UndefinedPlaceholder || // + object instanceof Boolean || // + object instanceof Integer || // + object instanceof BigInteger || // + object instanceof Double || // + object instanceof RubyBasicObject || // + object instanceof RubyMethod || // + object instanceof NilPlaceholder || // + object instanceof RubyMethod; + } + + public static boolean shouldObjectsBeVisible(Object... objects) { + for (Object object : objects) { + if (!shouldObjectBeVisible(object)) { + return false; + } + } + + return true; + } + + public void setCurrentDirectory(String currentDirectory) { + this.currentDirectory = currentDirectory; + } + + public String getCurrentDirectory() { + return currentDirectory; + } + + public POSIX getPOSIX() { + return posix; + } + + public AtExitManager getAtExitManager() { + return atExitManager; + } + + public SourceManager getSourceManager() { + return sourceManager; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyParser.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; + +/** + * Interface to a Ruby parser. + */ +public interface RubyParser { + + public static enum ParserContext { + TOP_LEVEL, SHELL, MODULE + } + + RubyParserResult parse(RubyContext context, Source source, ParserContext parserContext, MaterializedFrame parentFrame); + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyParserResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/RubyParserResult.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +/** + * The result of parsing Ruby code is a root node and a frame descriptor for the method in that + * root. The root node will always be a {@code RubyRootNode}, but this package is below the nodes + * package so currently cannot refer to it. + */ +public class RubyParserResult { + + private RootNode rootNode; + private FrameDescriptor frameDescriptor; + + public RubyParserResult(RootNode rootNode, FrameDescriptor frameDescriptor) { + assert rootNode != null; + assert frameDescriptor != null; + + this.rootNode = rootNode; + this.frameDescriptor = frameDescriptor; + } + + public RootNode getRootNode() { + return rootNode; + } + + public FrameDescriptor getFrameDescriptor() { + return frameDescriptor; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/ShellResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/ShellResult.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime; + +import com.oracle.truffle.api.frame.*; + +/** + * The result of executing a line in a shell is a result value and the final frame containing any + * local variables set. + */ +public class ShellResult { + + private final Object result; + private final MaterializedFrame frame; + + public ShellResult(Object result, MaterializedFrame frame) { + assert RubyContext.shouldObjectBeVisible(result); + assert frame != null; + + this.result = result; + this.frame = frame; + } + + public Object getResult() { + return result; + } + + public MaterializedFrame getFrame() { + return frame; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/UndefinedPlaceholder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/UndefinedPlaceholder.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime; + +/** + * The {@link UndefinedPlaceholder} is a value that represents an undefined value in Ruby. This is + * used to differentiate between nil and the true absence of a value, such as an argument that has + * not been passed. + */ +public final class UndefinedPlaceholder { + + public static final UndefinedPlaceholder INSTANCE = new UndefinedPlaceholder(); + + private UndefinedPlaceholder() { + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/configuration/Configuration.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/configuration/Configuration.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.configuration; + +import java.io.*; + +import com.oracle.truffle.ruby.runtime.*; + +/** + * Configurable, immutable global parameters for Ruby. + */ +public class Configuration { + + private final String standardLibrary; + + private final RubyVersion rubyVersion; + + private final boolean verbose; + private final int warningLevel; + private final int taintCheckLevel; + + private final String defaultExternalEncoding; + private final String defaultInternalEncoding; + + private final boolean debug; + private final boolean trace; + private final boolean fullObjectSpace; + + private final boolean printParseTree; + private final boolean printExecutedFiles; + private final boolean printSpiltInstanceVariables; + private final boolean printUninitializedCalls; + private final boolean printJavaExceptions; + private final boolean printRubyExceptions; + + private final PrintStream standardOut; + private final InputReader inputReader; + + public Configuration(ConfigurationBuilder builder) { + assert builder != null; + + standardLibrary = builder.getStandardLibrary(); + + rubyVersion = builder.getRubyVersion(); + + verbose = builder.getVerbose(); + warningLevel = builder.getWarningLevel(); + taintCheckLevel = builder.getTaintCheckLevel(); + + defaultExternalEncoding = builder.getDefaultExternalEncoding(); + defaultInternalEncoding = builder.getDefaultInternalEncoding(); + + debug = builder.getDebug(); + trace = builder.getTrace(); + fullObjectSpace = builder.getFullObjectSpace(); + + printParseTree = builder.getPrintParseTree(); + printExecutedFiles = builder.getPrintExecutedFiles(); + printSpiltInstanceVariables = builder.getPrintSpiltInstanceVariables(); + printUninitializedCalls = builder.getPrintUninitializedCalls(); + printJavaExceptions = builder.getPrintJavaExceptions(); + printRubyExceptions = builder.getPrintRubyExceptions(); + + standardOut = builder.getStandardOut(); + inputReader = builder.getInputReader(); + } + + public String getStandardLibrary() { + return standardLibrary; + } + + public RubyVersion getRubyVersion() { + return rubyVersion; + } + + public boolean getDebug() { + return debug; + } + + public boolean getVerbose() { + return verbose; + } + + public int getWarningLevel() { + return warningLevel; + } + + public int getTaintCheckLevel() { + return taintCheckLevel; + } + + public String getDefaultExternalEncoding() { + return defaultExternalEncoding; + } + + public String getDefaultInternalEncoding() { + return defaultInternalEncoding; + } + + public boolean getTrace() { + return trace; + } + + public boolean getFullObjectSpace() { + return fullObjectSpace; + } + + public boolean getPrintParseTree() { + return printParseTree; + } + + public boolean getPrintExecutedFiles() { + return printExecutedFiles; + } + + public boolean getPrintSpiltInstanceVariables() { + return printSpiltInstanceVariables; + } + + public boolean getPrintUninitializedCalls() { + return printUninitializedCalls; + } + + public boolean getPrintJavaExceptions() { + return printJavaExceptions; + } + + public boolean getPrintRubyExceptions() { + return printRubyExceptions; + } + + public PrintStream getStandardOut() { + return standardOut; + } + + public InputReader getInputReader() { + return inputReader; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/configuration/ConfigurationBuilder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/configuration/ConfigurationBuilder.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.configuration; + +import java.io.*; + +import com.oracle.truffle.ruby.runtime.*; + +/** + * The mutable counterpart to {@link Configuration}. + */ +public class ConfigurationBuilder { + + /** + * The path of the JRuby packaging of the Ruby standard library within our source tree. + */ + public static final String JRUBY_STDLIB_JAR = "lib/jruby-stdlib-1.7.4.jar"; + + private String standardLibrary = JRUBY_STDLIB_JAR; + + private RubyVersion rubyVersion = RubyVersion.RUBY_19; + + private boolean debug = true; + private boolean verbose = false; + private int warningLevel = 0; + private int taintCheckLevel = 0; + + private String defaultExternalEncoding = null; + private String defaultInternalEncoding = null; + + private boolean trace = true; + private boolean fullObjectSpace = false; + + private boolean printParseTree = false; + private boolean printExecutedFiles = false; + private boolean printSpiltInstanceVariables = false; + private boolean printUninitializedCalls = false; + private boolean printJavaExceptions = false; + private boolean printRubyExceptions = false; + + private PrintStream standardOut = System.out; + + private InputReader inputReader = new InputReader() { + + private final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + + @Override + public String readLine(String prompt) throws IOException { + System.err.print(prompt); + return reader.readLine(); + } + + }; + + public ConfigurationBuilder() { + } + + public ConfigurationBuilder(Configuration configuration) { + assert configuration != null; + + standardLibrary = configuration.getStandardLibrary(); + + rubyVersion = configuration.getRubyVersion(); + + debug = configuration.getDebug(); + verbose = configuration.getVerbose(); + warningLevel = configuration.getWarningLevel(); + taintCheckLevel = configuration.getTaintCheckLevel(); + + defaultExternalEncoding = configuration.getDefaultExternalEncoding(); + defaultInternalEncoding = configuration.getDefaultInternalEncoding(); + + trace = configuration.getTrace(); + fullObjectSpace = configuration.getFullObjectSpace(); + + printParseTree = configuration.getPrintParseTree(); + printExecutedFiles = configuration.getPrintExecutedFiles(); + printSpiltInstanceVariables = configuration.getPrintSpiltInstanceVariables(); + printUninitializedCalls = configuration.getPrintUninitializedCalls(); + printJavaExceptions = configuration.getPrintJavaExceptions(); + printRubyExceptions = configuration.getPrintRubyExceptions(); + + standardOut = configuration.getStandardOut(); + } + + public String getStandardLibrary() { + return standardLibrary; + } + + public void setStandardLibrary(String standardLibrary) { + assert standardLibrary != null; + this.standardLibrary = standardLibrary; + } + + public RubyVersion getRubyVersion() { + return rubyVersion; + } + + public void setRubyVersion(RubyVersion rubyVersion) { + assert rubyVersion != null; + this.rubyVersion = rubyVersion; + } + + public boolean getDebug() { + return debug; + } + + public void setDebug(boolean debug) { + this.debug = debug; + } + + public boolean getVerbose() { + return verbose; + } + + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + public int getWarningLevel() { + return warningLevel; + } + + public void setWarningLevel(int warningLevel) { + this.warningLevel = warningLevel; + } + + public int getTaintCheckLevel() { + return taintCheckLevel; + } + + public void setTaintCheckLevel(int taintCheckLevel) { + this.taintCheckLevel = taintCheckLevel; + } + + public String getDefaultExternalEncoding() { + return defaultExternalEncoding; + } + + public void setDefaultExternalEncoding(String defaultExternalEncoding) { + assert defaultExternalEncoding != null; + this.defaultExternalEncoding = defaultExternalEncoding; + } + + public String getDefaultInternalEncoding() { + return defaultInternalEncoding; + } + + public void setDefaultInternalEncoding(String defaultInternalEncoding) { + assert defaultInternalEncoding != null; + this.defaultInternalEncoding = defaultInternalEncoding; + } + + public boolean getTrace() { + return trace; + } + + public void setTrace(boolean trace) { + this.trace = trace; + } + + public boolean getFullObjectSpace() { + return fullObjectSpace; + } + + public void setFullObjectSpace(boolean fullObjectSpace) { + this.fullObjectSpace = fullObjectSpace; + } + + public boolean getPrintParseTree() { + return printParseTree; + } + + public void setPrintParseTree(boolean printParseTree) { + this.printParseTree = printParseTree; + } + + public boolean getPrintExecutedFiles() { + return printExecutedFiles; + } + + public void setPrintExecutedFiles(boolean printExecutedFiles) { + this.printExecutedFiles = printExecutedFiles; + } + + public boolean getPrintSpiltInstanceVariables() { + return printSpiltInstanceVariables; + } + + public void setPrintSpiltInstanceVariables(boolean printSpiltInstanceVariables) { + this.printSpiltInstanceVariables = printSpiltInstanceVariables; + } + + public boolean getPrintUninitializedCalls() { + return printUninitializedCalls; + } + + public void setPrintUninitializedCalls(boolean printUninitializedCalls) { + this.printUninitializedCalls = printUninitializedCalls; + } + + public boolean getPrintJavaExceptions() { + return printJavaExceptions; + } + + public void setPrintJavaExceptions(boolean printJavaExceptions) { + this.printJavaExceptions = printJavaExceptions; + } + + public boolean getPrintRubyExceptions() { + return printRubyExceptions; + } + + public void setPrintRubyExceptions(boolean printRubyExceptions) { + this.printRubyExceptions = printRubyExceptions; + } + + public PrintStream getStandardOut() { + return standardOut; + } + + public void setStandardOut(PrintStream standardOut) { + assert standardOut != null; + this.standardOut = standardOut; + } + + public InputReader getInputReader() { + return inputReader; + } + + public void setInputReader(InputReader lineReader) { + assert lineReader != null; + this.inputReader = lineReader; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/configuration/RubyVersion.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/configuration/RubyVersion.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.configuration; + +/** + * A Ruby version that we want to be compatible with. + */ +public enum RubyVersion { + RUBY_18("1.8.7", 374), RUBY_19("1.9.3", 448), RUBY_20("2.0.0", 247), RUBY_21("2.1.0", 0); + + private final String version; + private final int patch; + + private RubyVersion(String version, int patch) { + this.version = version; + this.patch = patch; + } + + public boolean is18OrEarlier() { + return this.compareTo(RUBY_18) <= 0; + } + + public boolean is19OrLater() { + return this.compareTo(RUBY_19) >= 0; + } + + public String getVersion() { + return version; + } + + public int getPatch() { + return patch; + } + + public String getShortName() { + return "Ruby" + getVersion(); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/BreakException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/BreakException.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.control; + +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * Controls a break from a control structure or method. + */ +public final class BreakException extends ControlFlowException { + + private final Object result; + + public BreakException(Object result) { + assert RubyContext.shouldObjectBeVisible(result); + + this.result = result; + } + + public Object getResult() { + return result; + } + + private static final long serialVersionUID = -8650123232850256133L; + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/BreakShellException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/BreakShellException.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.control; + +import com.oracle.truffle.api.nodes.*; + +/** + * Controls breaking out of a shell. + */ +public final class BreakShellException extends ControlFlowException { + + private static final long serialVersionUID = 6448983812696841922L; + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/ContinuationReturnException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/ContinuationReturnException.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.control; + +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * Controls return from a continuation. + */ +public final class ContinuationReturnException extends ControlFlowException { + + private final RubyContinuation continuation; + private final Object value; + + public ContinuationReturnException(RubyContinuation continuation, Object value) { + assert continuation != null; + assert RubyContext.shouldObjectBeVisible(value); + + this.continuation = continuation; + this.value = value; + } + + /** + * Get the continuation that caused this. + */ + public RubyContinuation getContinuation() { + return continuation; + } + + /** + * Get the value that has been returned. + */ + public Object getValue() { + return value; + } + + private static final long serialVersionUID = 6215834704293311504L; + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/ExceptionTranslator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/ExceptionTranslator.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.control; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +public final class ExceptionTranslator { + + /** + * Translate a Java exception into a Ruby exception. + */ + public static RubyBasicObject translateException(RubyContext context, Throwable exception) { + assert context != null; + assert exception != null; + + CompilerAsserts.neverPartOfCompilation(); + + // RaiseException already includes the Ruby exception + + if (exception instanceof RaiseException) { + return ((RaiseException) exception).getRubyException(); + } + + // Translate divide by zero into ZeroDivisionError + + if (exception instanceof ArithmeticException && (exception.getMessage().endsWith("divide by zero") || exception.getMessage().endsWith("/ by zero"))) { + return new RubyException(context.getCoreLibrary().getZeroDivisionErrorClass(), "divided by 0"); + } + + /* + * If we can't translate the exception into a Ruby exception, then the error is ours and we + * report it as as RubyTruffleError. If a programmer sees this then it's a bug in our + * implementation. + */ + + if (context.getConfiguration().getPrintJavaExceptions()) { + exception.printStackTrace(); + } + + String message; + + if (exception.getMessage() == null) { + message = exception.getClass().getSimpleName(); + } else { + message = exception.getMessage(); + } + + return new RubyException(context.getCoreLibrary().getRubyTruffleErrorClass(), message); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/NextException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/NextException.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.control; + +import com.oracle.truffle.api.nodes.*; + +/** + * Controls moving to the next iteration in a control structure or method. + */ +public final class NextException extends ControlFlowException { + + private static final long serialVersionUID = -302759969186731457L; + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/QuitException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/QuitException.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.control; + +import com.oracle.truffle.api.nodes.*; + +/** + * Controls breaking out of all executions and ending Ruby execution. + */ +public final class QuitException extends ControlFlowException { + + private static final long serialVersionUID = -3568511099628564190L; + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/RaiseException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/RaiseException.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.control; + +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Ruby exceptions are just Ruby objects, so they cannot also be exceptions unless we made all Ruby + * objects exceptions. A simpler approach is to wrap Ruby exceptions in Java exceptions when we want + * to throw them. The error messages match MRI. Note that throwing is different to raising in Ruby, + * which is the reason we have both {@link ThrowException} and {@link RaiseException}. + */ +public class RaiseException extends RuntimeException { + + private final RubyBasicObject rubyException; + + public RaiseException(RubyBasicObject rubyException) { + this.rubyException = rubyException; + } + + @Override + public String toString() { + return rubyException.toString(); + } + + @Override + public String getMessage() { + return rubyException.toString(); + } + + public RubyBasicObject getRubyException() { + return rubyException; + } + + private static final long serialVersionUID = 7501185855599094740L; + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/RedoException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/RedoException.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.control; + +import com.oracle.truffle.api.nodes.*; + +/** + * Controls re-doing an iteration in a control structure or method. + */ +public final class RedoException extends ControlFlowException { + + private static final long serialVersionUID = -4717868827111714052L; + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/RetryException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/RetryException.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.control; + +import com.oracle.truffle.api.nodes.*; + +/** + * Controls re-trying an iteration in a control structure or method. + */ +public final class RetryException extends ControlFlowException { + + private static final long serialVersionUID = -1675586631300635765L; + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/ReturnException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/ReturnException.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.control; + +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * Controls an explicit return from a method. + */ +public final class ReturnException extends ControlFlowException { + + private final long returnID; + private final Object value; + + public ReturnException(long returnID, Object value) { + assert RubyContext.shouldObjectBeVisible(value); + + this.returnID = returnID; + this.value = value; + } + + /** + * Return the return ID of this return that identifies where it intends to return to. + */ + public long getReturnID() { + return returnID; + } + + /** + * Get the value that has been returned. + */ + public Object getValue() { + return value; + } + + private static final long serialVersionUID = -9177536212065610691L; + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/ThrowException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/control/ThrowException.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.control; + +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * Controls throwing a value. Note that throwing is different to raising in Ruby, which is the + * reason we have both {@link ThrowException} and {@link RaiseException}. + */ +public class ThrowException extends ControlFlowException { + + private final Object tag; + private final Object value; + + public ThrowException(Object tag, Object value) { + assert tag != null; + assert RubyContext.shouldObjectBeVisible(value); + + this.tag = tag; + this.value = value; + } + + public Object getTag() { + return tag; + } + + public Object getValue() { + return value; + } + + private static final long serialVersionUID = 8693305627979840677L; + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/CoreLibrary.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/CoreLibrary.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,649 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import java.io.*; +import java.math.*; +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.array.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +public class CoreLibrary { + + private final RubyContext context; + + private RubyClass argumentErrorClass; + private RubyClass arrayClass; + private RubyClass basicObjectClass; + private RubyClass bignumClass; + private RubyClass bindingClass; + private RubyClass classClass; + private RubyClass continuationClass; + private RubyClass dirClass; + private RubyClass exceptionClass; + private RubyClass falseClass; + private RubyClass fiberClass; + private RubyClass fileClass; + private RubyClass fixnumClass; + private RubyClass floatClass; + private RubyClass hashClass; + private RubyClass integerClass; + private RubyClass ioClass; + private RubyClass loadErrorClass; + private RubyClass localJumpErrorClass; + private RubyClass matchDataClass; + private RubyClass moduleClass; + private RubyClass nameErrorClass; + private RubyClass nilClass; + private RubyClass noMethodErrorClass; + private RubyClass numericClass; + private RubyClass objectClass; + private RubyClass procClass; + private RubyClass processClass; + private RubyClass rangeClass; + private RubyClass rangeErrorClass; + private RubyClass regexpClass; + private RubyClass rubyTruffleErrorClass; + private RubyClass runtimeErrorClass; + private RubyClass standardErrorClass; + private RubyClass stringClass; + private RubyClass structClass; + private RubyClass symbolClass; + private RubyClass syntaxErrorClass; + private RubyClass systemCallErrorClass; + private RubyClass systemExitClass; + private RubyClass threadClass; + private RubyClass timeClass; + private RubyClass trueClass; + private RubyClass typeErrorClass; + private RubyClass zeroDivisionErrorClass; + + private RubyModule comparableModule; + private RubyModule configModule; + private RubyModule errnoModule; + private RubyModule kernelModule; + private RubyModule mathModule; + private RubyModule objectSpaceModule; + private RubyModule signalModule; + + private RubyModule debugModule; + private RubyArray argv; + private RubyBasicObject globalVariablesObject; + private RubyBasicObject mainObject; + private RubyFalseClass falseObject; + private RubyNilClass nilObject; + private RubyTrueClass trueObject; + + public CoreLibrary(RubyContext context) { + this.context = context; + } + + public void initialize() { + // Create the cyclic classes and modules + + classClass = new RubyClass.RubyClassClass(context); + basicObjectClass = new RubyClass(context, classClass, null, null, "BasicObject"); + objectClass = new RubyClass(null, basicObjectClass, "Object"); + moduleClass = new RubyModule.RubyModuleClass(context); + + // Close the cycles + + moduleClass.unsafeSetRubyClass(classClass); + classClass.unsafeSetSuperclass(moduleClass); + moduleClass.unsafeSetSuperclass(objectClass); + classClass.unsafeSetRubyClass(classClass); + + // Create all other classes and modules + + numericClass = new RubyClass(null, objectClass, "Numeric"); + integerClass = new RubyClass(null, numericClass, "Integer"); + + exceptionClass = new RubyException.RubyExceptionClass(objectClass, "Exception"); + standardErrorClass = new RubyException.RubyExceptionClass(exceptionClass, "StandardError"); + + ioClass = new RubyClass(null, objectClass, "IO"); + + argumentErrorClass = new RubyException.RubyExceptionClass(standardErrorClass, "ArgumentError"); + arrayClass = new RubyArray.RubyArrayClass(objectClass); + bignumClass = new RubyClass(null, integerClass, "Bignum"); + bindingClass = new RubyClass(null, objectClass, "Binding"); + continuationClass = new RubyClass(null, objectClass, "Continuation"); + comparableModule = new RubyModule(moduleClass, null, "Comparable"); + configModule = new RubyModule(moduleClass, null, "Config"); + debugModule = new RubyModule(moduleClass, null, "Debug"); + dirClass = new RubyClass(null, objectClass, "Dir"); + errnoModule = new RubyModule(moduleClass, null, "Errno"); + falseClass = new RubyClass(null, objectClass, "FalseClass"); + fiberClass = new RubyFiber.RubyFiberClass(objectClass); + fileClass = new RubyClass(null, ioClass, "File"); + fixnumClass = new RubyClass(null, integerClass, "Fixnum"); + floatClass = new RubyClass(null, objectClass, "Float"); + hashClass = new RubyHash.RubyHashClass(objectClass); + kernelModule = new RubyModule(moduleClass, null, "Kernel"); + loadErrorClass = new RubyException.RubyExceptionClass(standardErrorClass, "LoadError"); + localJumpErrorClass = new RubyException.RubyExceptionClass(standardErrorClass, "LocalJumpError"); + matchDataClass = new RubyClass(null, objectClass, "MatchData"); + mathModule = new RubyModule(moduleClass, null, "Math"); + nameErrorClass = new RubyClass(null, standardErrorClass, "NameError"); + nilClass = new RubyClass(null, objectClass, "NilClass"); + noMethodErrorClass = new RubyException.RubyExceptionClass(standardErrorClass, "NoMethodError"); + objectSpaceModule = new RubyModule(moduleClass, null, "ObjectSpace"); + procClass = new RubyProc.RubyProcClass(objectClass); + processClass = new RubyClass(null, objectClass, "Process"); + rangeClass = new RubyClass(null, objectClass, "Range"); + rangeErrorClass = new RubyException.RubyExceptionClass(standardErrorClass, "RangeError"); + regexpClass = new RubyRegexp.RubyRegexpClass(objectClass); + rubyTruffleErrorClass = new RubyException.RubyExceptionClass(standardErrorClass, "RubyTruffleError"); + runtimeErrorClass = new RubyException.RubyExceptionClass(standardErrorClass, "RuntimeError"); + stringClass = new RubyString.RubyStringClass(objectClass); + structClass = new RubyClass(null, ioClass, "Struct"); + signalModule = new RubyModule(moduleClass, null, "Signal"); + symbolClass = new RubyClass(null, objectClass, "Symbol"); + syntaxErrorClass = new RubyException.RubyExceptionClass(standardErrorClass, "SyntaxError"); + systemCallErrorClass = new RubyException.RubyExceptionClass(standardErrorClass, "SystemCallError"); + systemExitClass = new RubyException.RubyExceptionClass(exceptionClass, "SystemExit"); + threadClass = new RubyThread.RubyThreadClass(objectClass); + timeClass = new RubyTime.RubyTimeClass(objectClass); + trueClass = new RubyClass(null, objectClass, "TrueClass"); + typeErrorClass = new RubyException.RubyExceptionClass(standardErrorClass, "TypeError"); + zeroDivisionErrorClass = new RubyException.RubyExceptionClass(standardErrorClass, "ZeroDivisionError"); + + // Includes + + objectClass.include(kernelModule); + + // Set constants + + objectClass.setConstant("RUBY_VERSION", new RubyString(stringClass, context.getConfiguration().getRubyVersion().getVersion())); + objectClass.setConstant("RUBY_PATCHLEVEL", context.getConfiguration().getRubyVersion().getPatch()); + objectClass.setConstant("RUBY_ENGINE", new RubyString(stringClass, "rubytruffle")); + objectClass.setConstant("RUBY_PLATFORM", new RubyString(stringClass, "jvm")); + + argv = new RubyArray(arrayClass, new ObjectArrayStore()); + objectClass.setConstant("ARGV", argv); + objectClass.setConstant("ENV", getEnv()); + + final RubyHash configHash = new RubyHash(hashClass); + configHash.put(new RubyString(stringClass, "ruby_install_name"), new RubyString(stringClass, "rubytruffle")); + configHash.put(new RubyString(stringClass, "RUBY_INSTALL_NAME"), new RubyString(stringClass, "rubytruffle")); + configHash.put(new RubyString(stringClass, "host_os"), new RubyString(stringClass, "unknown")); + configHash.put(new RubyString(stringClass, "exeext"), new RubyString(stringClass, "")); + configHash.put(new RubyString(stringClass, "EXEEXT"), new RubyString(stringClass, "rubytruffle")); + configModule.setConstant("CONFIG", configHash); + objectClass.setConstant("RbConfig", configModule); + + mathModule.setConstant("PI", Math.PI); + + fileClass.setConstant("SEPARATOR", new RubyString(stringClass, File.separator)); + fileClass.setConstant("Separator", new RubyString(stringClass, File.separator)); + fileClass.setConstant("ALT_SEPARATOR", NilPlaceholder.INSTANCE); + fileClass.setConstant("PATH_SEPARATOR", new RubyString(stringClass, File.pathSeparator)); + fileClass.setConstant("FNM_SYSCASE", 0); + + errnoModule.setConstant("ENOENT", new RubyClass(null, systemCallErrorClass, "ENOENT")); + errnoModule.setConstant("EPERM", new RubyClass(null, systemCallErrorClass, "EPERM")); + errnoModule.setConstant("ENOTEMPTY", new RubyClass(null, systemCallErrorClass, "ENOTEMPTY")); + errnoModule.setConstant("EEXIST", new RubyClass(null, systemCallErrorClass, "EEXIST")); + errnoModule.setConstant("EXDEV", new RubyClass(null, systemCallErrorClass, "EXDEV")); + errnoModule.setConstant("EACCES", new RubyClass(null, systemCallErrorClass, "EACCES")); + + // Add all classes and modules as constants in Object + + final RubyModule[] modules = {argumentErrorClass, // + arrayClass, // + basicObjectClass, // + bignumClass, // + bindingClass, // + classClass, // + continuationClass, // + comparableModule, // + configModule, // + debugModule, // + dirClass, // + errnoModule, // + exceptionClass, // + falseClass, // + fiberClass, // + fileClass, // + fixnumClass, // + floatClass, // + hashClass, // + integerClass, // + ioClass, // + kernelModule, // + loadErrorClass, // + localJumpErrorClass, // + matchDataClass, // + mathModule, // + moduleClass, // + nameErrorClass, // + nilClass, // + noMethodErrorClass, // + numericClass, // + objectClass, // + objectSpaceModule, // + procClass, // + processClass, // + rangeClass, // + rangeErrorClass, // + regexpClass, // + rubyTruffleErrorClass, // + runtimeErrorClass, // + signalModule, // + standardErrorClass, // + stringClass, // + structClass, // + symbolClass, // + syntaxErrorClass, // + systemCallErrorClass, // + systemExitClass, // + threadClass, // + timeClass, // + trueClass, // + typeErrorClass, // + zeroDivisionErrorClass}; + + for (RubyModule module : modules) { + objectClass.setConstant(module.getName(), module); + } + + // Create some key objects + + mainObject = new RubyObject(objectClass); + nilObject = new RubyNilClass(nilClass); + trueObject = new RubyTrueClass(trueClass); + falseObject = new RubyFalseClass(falseClass); + + // Create the globals object + + globalVariablesObject = new RubyBasicObject(objectClass); + globalVariablesObject.switchToPrivateLayout(); + globalVariablesObject.setInstanceVariable("$:", new RubyArray(arrayClass, new ObjectArrayStore())); + } + + public void initializeAfterMethodsAdded() { + bignumClass.getSingletonClass().undefMethod("new"); + falseClass.getSingletonClass().undefMethod("new"); + fixnumClass.getSingletonClass().undefMethod("new"); + floatClass.getSingletonClass().undefMethod("new"); + integerClass.getSingletonClass().undefMethod("new"); + nilClass.getSingletonClass().undefMethod("new"); + numericClass.getSingletonClass().undefMethod("new"); + trueClass.getSingletonClass().undefMethod("new"); + } + + public RubyBasicObject box(Object object) { + assert RubyContext.shouldObjectBeVisible(object); + + // TODO(cs): pool common object instances like small Fixnums? + + if (object instanceof RubyBasicObject) { + return (RubyBasicObject) object; + } + + if (object instanceof Boolean) { + if ((boolean) object) { + return trueObject; + } else { + return falseObject; + } + } + + if (object instanceof Integer) { + return new RubyFixnum(fixnumClass, (int) object); + } + + if (object instanceof BigInteger) { + return new RubyBignum(bignumClass, (BigInteger) object); + } + + if (object instanceof Double) { + return new RubyFloat(floatClass, (double) object); + } + + if (object instanceof NilPlaceholder) { + return nilObject; + } + + CompilerDirectives.transferToInterpreter(); + + throw new UnsupportedOperationException("Don't know how to box " + object.getClass().getName()); + } + + public RubyException runtimeError(String message) { + return new RubyException(runtimeErrorClass, message); + } + + public RubyException frozenError(String className) { + return runtimeError(String.format("can't modify frozen %s", className)); + } + + public RubyException argumentError(String message) { + return new RubyException(argumentErrorClass, message); + } + + public RubyException argumentError(int passed, int required) { + return argumentError(String.format("wrong number of arguments (%d for %d)", passed, required)); + } + + public RubyException argumentErrorUncaughtThrow(Object tag) { + return argumentError(String.format("uncaught throw `%s'", tag)); + } + + public RubyException localJumpError(String message) { + return new RubyException(localJumpErrorClass, message); + } + + public RubyException unexpectedReturn() { + return localJumpError("unexpected return"); + } + + public RubyException typeError(String message) { + return new RubyException(typeErrorClass, message); + } + + public RubyException typeError(String from, String to) { + return typeError(String.format("can't convert %s to %s", from, to)); + } + + public RubyException typeErrorIsNotA(String value, String expectedType) { + return typeError(String.format("%s is not a %s", value, expectedType)); + } + + public RubyException typeErrorNeedsToBe(String name, String expectedType) { + return typeError(String.format("%s needs to be %s", name, expectedType)); + } + + public RubyException rangeError(String message) { + return new RubyException(rangeErrorClass, message); + } + + public RubyException nameError(String message) { + return new RubyException(nameErrorClass, message); + } + + public RubyException nameErrorUninitializedConstant(String name) { + return nameError(String.format("uninitialized constant %s", name)); + } + + public RubyException nameErrorNoMethod(String name, String object) { + return nameError(String.format("undefined local variable or method `%s' for %s", name, object)); + } + + public RubyException nameErrorInstanceNameNotAllowable(String name) { + return nameError(String.format("`%s' is not allowable as an instance variable name", name)); + } + + public RubyException nameErrorUncaughtThrow(Object tag) { + return nameError(String.format("uncaught throw `%s'", tag)); + } + + public RubyException noMethodError(String message) { + return new RubyException(context.getCoreLibrary().getNoMethodErrorClass(), message); + } + + public RubyException noMethodError(String name, String object) { + return noMethodError(String.format("undefined method `%s' for %s", name, object)); + } + + public RubyException loadError(String message) { + return new RubyException(context.getCoreLibrary().getLoadErrorClass(), message); + } + + public RubyException loadErrorCannotLoad(String name) { + return loadError(String.format("cannot load such file -- %s", name)); + } + + public RubyException zeroDivisionError() { + return new RubyException(context.getCoreLibrary().getZeroDivisionErrorClass(), "divided by 0"); + } + + public RubyContext getContext() { + return context; + } + + public RubyClass getArgumentErrorClass() { + return argumentErrorClass; + } + + public RubyClass getArrayClass() { + return arrayClass; + } + + public RubyClass getBasicObjectClass() { + return basicObjectClass; + } + + public RubyClass getBignumClass() { + return bignumClass; + } + + public RubyClass getBindingClass() { + return bindingClass; + } + + public RubyClass getClassClass() { + return classClass; + } + + public RubyModule getComparableClass() { + return comparableModule; + } + + public RubyClass getContinuationClass() { + return continuationClass; + } + + public RubyClass getDirClass() { + return dirClass; + } + + public RubyClass getExceptionClass() { + return exceptionClass; + } + + public RubyClass getFalseClass() { + return falseClass; + } + + public RubyClass getFiberClass() { + return fiberClass; + } + + public RubyClass getFileClass() { + return fileClass; + } + + public RubyClass getFixnumClass() { + return fixnumClass; + } + + public RubyClass getFloatClass() { + return floatClass; + } + + public RubyClass getHashClass() { + return hashClass; + } + + public RubyClass getIntegerClass() { + return integerClass; + } + + public RubyClass getIoClass() { + return ioClass; + } + + public RubyClass getLoadErrorClass() { + return loadErrorClass; + } + + public RubyClass getLocalJumpErrorClass() { + return localJumpErrorClass; + } + + public RubyClass getMatchDataClass() { + return matchDataClass; + } + + public RubyClass getModuleClass() { + return moduleClass; + } + + public RubyClass getNameErrorClass() { + return nameErrorClass; + } + + public RubyClass getNilClass() { + return nilClass; + } + + public RubyClass getNoMethodErrorClass() { + return noMethodErrorClass; + } + + public RubyClass getNumericClass() { + return numericClass; + } + + public RubyClass getObjectClass() { + return objectClass; + } + + public RubyClass getProcClass() { + return procClass; + } + + public RubyClass getProcessClass() { + return processClass; + } + + public RubyClass getRangeClass() { + return rangeClass; + } + + public RubyClass getRangeErrorClass() { + return rangeErrorClass; + } + + public RubyClass getRegexpClass() { + return regexpClass; + } + + public RubyClass getRubyTruffleErrorClass() { + return rubyTruffleErrorClass; + } + + public RubyClass getRuntimeErrorClass() { + return runtimeErrorClass; + } + + public RubyModule getSignalModule() { + return signalModule; + } + + public RubyClass getStandardErrorClass() { + return standardErrorClass; + } + + public RubyClass getStringClass() { + return stringClass; + } + + public RubyClass getStructClass() { + return structClass; + } + + public RubyClass getSymbolClass() { + return symbolClass; + } + + public RubyClass getSyntaxErrorClass() { + return syntaxErrorClass; + } + + public RubyClass getSystemCallErrorClass() { + return systemCallErrorClass; + } + + public RubyClass getThreadClass() { + return threadClass; + } + + public RubyClass getTimeClass() { + return timeClass; + } + + public RubyClass getTrueClass() { + return trueClass; + } + + public RubyClass getTypeErrorClass() { + return typeErrorClass; + } + + public RubyClass getZeroDivisionErrorClass() { + return zeroDivisionErrorClass; + } + + public RubyModule getKernelModule() { + return kernelModule; + } + + public RubyModule getMathModule() { + return mathModule; + } + + public RubyModule getObjectSpaceModule() { + return objectSpaceModule; + } + + public RubyModule getDebugModule() { + return debugModule; + } + + public RubyArray getArgv() { + return argv; + } + + public RubyBasicObject getGlobalVariablesObject() { + return globalVariablesObject; + } + + public RubyBasicObject getMainObject() { + return mainObject; + } + + public RubyFalseClass getFalseObject() { + return falseObject; + } + + public RubyNilClass getNilObject() { + return nilObject; + } + + public RubyTrueClass getTrueObject() { + return trueObject; + } + + public RubyHash getEnv() { + final RubyHash hash = new RubyHash(context.getCoreLibrary().getHashClass()); + + for (Map.Entry variable : System.getenv().entrySet()) { + hash.put(context.makeString(variable.getKey()), context.makeString(variable.getValue())); + } + + return hash; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/GeneralConversions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/GeneralConversions.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import java.math.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.ruby.runtime.*; + +public class GeneralConversions { + + /** + * Convert a value to a boolean, without doing any lookup. + */ + public static boolean toBoolean(Object value) { + assert value != null; + + if (value instanceof NilPlaceholder) { + return false; + } + + if (value instanceof Boolean) { + return (boolean) value; + } + + if (value instanceof RubyTrueClass) { + return true; + } + + if (value instanceof RubyFalseClass) { + return false; + } + + return true; + } + + /** + * Convert a value to a {@code Fixnum}, without doing any lookup. + */ + public static int toFixnum(Object value) { + assert value != null; + + if (value instanceof NilPlaceholder || value instanceof RubyNilClass) { + return 0; + } + + if (value instanceof Integer) { + return (int) value; + } + + if (value instanceof RubyFixnum) { + return ((RubyFixnum) value).getValue(); + } + + if (value instanceof BigInteger) { + throw new UnsupportedOperationException(); + } + + if (value instanceof RubyBignum) { + throw new UnsupportedOperationException(); + } + + if (value instanceof Double) { + return (int) (double) value; + } + + if (value instanceof RubyFloat) { + return (int) ((RubyFloat) value).getValue(); + } + + CompilerDirectives.transferToInterpreter(); + + throw new UnsupportedOperationException(value.getClass().toString()); + } + + /** + * Convert a value to a {@code Float}, without doing any lookup. + */ + public static double toFloat(Object value) { + assert value != null; + + if (value instanceof NilPlaceholder || value instanceof RubyNilClass) { + return 0; + } + + if (value instanceof Integer) { + return (int) value; + } + + if (value instanceof RubyFixnum) { + return ((RubyFixnum) value).getValue(); + } + + if (value instanceof BigInteger) { + return ((BigInteger) value).doubleValue(); + } + + if (value instanceof RubyBignum) { + return ((RubyBignum) value).getValue().doubleValue(); + } + + if (value instanceof Double) { + return (double) value; + } + + if (value instanceof RubyFloat) { + return ((RubyFloat) value).getValue(); + } + + CompilerDirectives.transferToInterpreter(); + + throw new UnsupportedOperationException(); + } + + /** + * Given a {@link BigInteger} value, produce either a {@code Fixnum} or {@code Bignum} . + */ + public static Object fixnumOrBignum(BigInteger value) { + assert value != null; + + if (value.compareTo(RubyFixnum.MIN_VALUE_BIG) >= 0 && value.compareTo(RubyFixnum.MAX_VALUE_BIG) <= 0) { + return value.intValue(); + } else { + return value; + } + } + + /** + * Given a {@code long} value, produce either a {@code Fixnum} or {@code Bignum} . + */ + public static Object fixnumOrBignum(long value) { + if (value >= RubyFixnum.MIN_VALUE && value <= RubyFixnum.MAX_VALUE) { + return (int) value; + } else { + return BigInteger.valueOf(value); + } + } + + /** + * Given a reference, produce either {@code nil} or the object. . + */ + public static Object instanceOrNil(Object object) { + if (object == null) { + return NilPlaceholder.INSTANCE; + } else { + return object; + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyBignum.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyBignum.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import java.math.*; + +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.array.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Represents the Ruby {@code Bignum} class. + */ +public class RubyBignum extends RubyObject implements Unboxable { + + private final BigInteger value; + + public RubyBignum(RubyClass bignumClass, BigInteger value) { + super(bignumClass); + + assert value != null; + + this.value = value; + } + + public BigInteger getValue() { + return value; + } + + public Object unbox() { + return value; + } + + public static RubyArray divMod(RubyContext context, BigInteger a, BigInteger b) { + final BigInteger[] quotientRemainder = a.divideAndRemainder(b); + + final Object quotient = GeneralConversions.fixnumOrBignum(quotientRemainder[0]); + final Object remainder = GeneralConversions.fixnumOrBignum(quotientRemainder[1]); + + final ObjectImmutablePairArrayStore store = new ObjectImmutablePairArrayStore(quotient, remainder); + return new RubyArray(context.getCoreLibrary().getArrayClass(), store); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof RubyBignum)) { + return false; + } + RubyBignum other = (RubyBignum) obj; + if (value == null) { + if (other.value != null) { + return false; + } + } else if (!value.equals(other.value)) { + return false; + } + return true; + } + + @Override + public String toString() { + return value.toString(); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyBinding.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyBinding.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import com.oracle.truffle.api.frame.*; + +/** + * Represents the Ruby {@code Binding} class. + */ +public class RubyBinding extends RubyObject { + + private final Object self; + private final MaterializedFrame frame; + + public RubyBinding(RubyClass bindingClass, Object self, MaterializedFrame frame) { + super(bindingClass); + + assert self != null; + assert frame != null; + + this.self = self; + this.frame = frame; + } + + public Object getSelf() { + return self; + } + + public MaterializedFrame getFrame() { + return frame; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyClass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyClass.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import java.util.*; + +import com.oracle.truffle.api.CompilerDirectives.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.lookup.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Represents the Ruby {@code Class} class. Note that most of the functionality you might associate + * with {@code Class} is actually in {@code Module}, implemented by {@link RubyModule}. + */ +public class RubyClass extends RubyModule { + + /** + * The class from which we create the object that is {@code Class}. A subclass of + * {@link RubyClass} so that we can override {@link #newInstance} and allocate a + * {@link RubyClass} rather than a normal {@link RubyBasicObject}. + */ + public static class RubyClassClass extends RubyClass { + + public RubyClassClass(RubyContext context) { + super(context, null, null, null, "Class"); + } + + @Override + public RubyBasicObject newInstance() { + return new RubyClass(null, getContext().getCoreLibrary().getObjectClass(), "(unnamed class)"); + } + + } + + @CompilationFinal private RubyClass superclass; + + // We maintain a list of subclasses so we can notify them when they need to update their layout. + private final Set subClasses = Collections.newSetFromMap(new WeakHashMap()); + + /* + * The layout to use for instances of this class - do not confuse with objectLayout, which is + * the layout for this object - the class. + */ + private ObjectLayout objectLayoutForInstances = null; + + public RubyClass(RubyModule parentModule, RubyClass rubySuperclass, String name) { + this(parentModule, rubySuperclass, name, false); + } + + public RubyClass(RubyModule parentModule, RubyClass rubySuperclass, String name, boolean isSingleton) { + this(rubySuperclass.getContext(), rubySuperclass.getContext().getCoreLibrary().getClassClass(), parentModule, rubySuperclass, name); + + if (!isSingleton) { + getSingletonClass(); + } + } + + /** + * This constructor supports initialization and solves boot-order problems and should not + * normally be used from outside this class. + */ + public RubyClass(RubyContext context, RubyClass classClass, RubyModule parentModule, RubyClass superclass, String name) { + super(context, classClass, parentModule, name); + + if (superclass == null) { + objectLayoutForInstances = ObjectLayout.EMPTY; + } else { + unsafeSetSuperclass(superclass); + } + } + + public RubyClass getSuperclass() { + assert superclass != null; + return superclass; + } + + @Override + public RubyClass getSingletonClass() { + if (rubySingletonClass == null) { + RubyClass singletonSuperclass; + + if (superclass == null) { + singletonSuperclass = getRubyClass(); + } else { + singletonSuperclass = superclass.getSingletonClass(); + } + + rubySingletonClass = new RubyClass(getParentModule(), singletonSuperclass, String.format("#", getName()), true); + + lookupNode = new LookupFork(rubySingletonClass, lookupNode); + } + + return rubySingletonClass; + } + + /** + * This method supports initialization and solves boot-order problems and should not normally be + * used. + */ + public void unsafeSetSuperclass(RubyClass newSuperclass) { + assert superclass == null; + + superclass = newSuperclass; + superclass.addDependent(this); + superclass.subClasses.add(this); + + include(superclass); + + objectLayoutForInstances = new ObjectLayout(getName(), getContext(), superclass.objectLayoutForInstances); + } + + public RubyBasicObject newInstance() { + return new RubyObject(this); + } + + /** + * Is an instance of this class assignable to some location expecting some other class? + */ + public boolean assignableTo(RubyClass otherClass) { + if (this == otherClass) { + return true; + } + + if (superclass == null) { + return false; + } + + return superclass.assignableTo(otherClass); + } + + /** + * Returns the object layout that objects of this class should use. Do not confuse with + * {@link #getObjectLayout}, which for {@link RubyClass} will return the layout of the class + * object itself. + */ + public ObjectLayout getObjectLayoutForInstances() { + return objectLayoutForInstances; + } + + /** + * Change the layout to be used for instances of this object. + */ + public void setObjectLayoutForInstances(ObjectLayout newObjectLayoutForInstances) { + objectLayoutForInstances = newObjectLayoutForInstances; + + for (RubyClass subClass : subClasses) { + subClass.renewObjectLayoutForInstances(); + } + } + + private void renewObjectLayoutForInstances() { + objectLayoutForInstances = objectLayoutForInstances.renew(getContext(), superclass.objectLayoutForInstances); + + for (RubyClass subClass : subClasses) { + subClass.renewObjectLayoutForInstances(); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyContinuation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyContinuation.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +/** + * Represents the Ruby {@code Continuation} class. We only support continuations that just move up + * the stack and are one-shot. + */ +public class RubyContinuation extends RubyObject { + + /* + * A continuation is dead if we have already resumed it once. We will not be able to resume it + * again due to the current implementation being an exception thrown to go back up the stack. + */ + private boolean dead = false; + + public RubyContinuation(RubyClass rubyClass) { + super(rubyClass); + } + + /** + * To enter a continuation means to remember the execution state at this point, reify that into + * an object, and then call the passed block. For our implementation, the continuation will be + * dead when this method resumes. + */ + public Object enter(RubyProc block) { + try { + return block.call(null, this); + } catch (ContinuationReturnException e) { + // Thrown in call + + // Check the exception is for this continuation + + if (e.getContinuation() == this) { + return e.getValue(); + } else { + throw e; + } + } finally { + dead = true; + } + } + + /** + * To call a continuation means to go back to the execution state when it was created. For our + * implementation we can only do this once, and only if that means jumping back up the stack. + */ + public void call(Object... args) { + if (dead) { + throw new UnsupportedOperationException("Only continuations that just move up the stack and are one-shot are supported"); + } + + Object returnValue; + + if (args.length == 0) { + returnValue = NilPlaceholder.INSTANCE; + } else if (args.length == 1) { + returnValue = args[0]; + } else { + returnValue = RubyArray.specializedFromObjects(getRubyClass().getContext().getCoreLibrary().getArrayClass(), args); + } + + // Caught in enter + + throw new ContinuationReturnException(this, returnValue); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyException.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Represents the Ruby {@code Exception} class. + */ +public class RubyException extends RubyObject { + + /** + * The class from which we create the object that is {@code Exception}. A subclass of + * {@link RubyClass} so that we can override {@link #newInstance} and allocate a + * {@link RubyException} rather than a normal {@link RubyBasicObject}. + */ + public static class RubyExceptionClass extends RubyClass { + + public RubyExceptionClass(RubyClass superClass, String name) { + super(null, superClass, name); + } + + @Override + public RubyBasicObject newInstance() { + return new RubyException(this); + } + + } + + private RubyString message; + + public RubyException(RubyClass rubyClass) { + super(rubyClass); + message = rubyClass.getContext().makeString("(object uninitialized)"); + } + + public RubyException(RubyClass rubyClass, String message) { + this(rubyClass, rubyClass.getContext().makeString(message)); + } + + public RubyException(RubyClass rubyClass, RubyString message) { + this(rubyClass); + initialize(message); + } + + public void initialize(RubyString setMessage) { + assert setMessage != null; + message = setMessage; + } + + public RubyString getMessage() { + return message; + } + + @Override + public String toString() { + return message.toString(); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyFalseClass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyFalseClass.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Represents the Ruby {@code FalseClass} class. + */ +public class RubyFalseClass extends RubyObject implements Unboxable { + + public RubyFalseClass(RubyClass objectClass) { + super(objectClass); + } + + public Object unbox() { + return false; + } + + @Override + public String toString() { + return "false"; + } + + @Override + public boolean equals(Object other) { + return other instanceof RubyFalseClass || (other instanceof Boolean && !((boolean) other)); + } + + @Override + public int hashCode() { + return Boolean.FALSE.hashCode(); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyFiber.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyFiber.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import java.util.concurrent.*; + +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.array.*; +import com.oracle.truffle.ruby.runtime.objects.*; +import com.oracle.truffle.ruby.runtime.subsystems.*; + +/** + * Represents the Ruby {@code Fiber} class. The current implementation uses Java threads and message + * passing. Note that the relationship between Java threads, Ruby threads and Ruby fibers is + * complex. A Java thread might be running a fiber that on difference resumptions is representing + * different Ruby threads. Take note of the lock contracts on {@link #waitForResume} and + * {@link #resume}. + */ +public class RubyFiber extends RubyObject { + + public static class RubyFiberClass extends RubyClass { + + public RubyFiberClass(RubyClass objectClass) { + super(null, objectClass, "Fiber"); + } + + @Override + public RubyBasicObject newInstance() { + return new RubyFiber(this, getContext().getFiberManager(), getContext().getThreadManager()); + } + + } + + private interface FiberMessage { + } + + private class FiberResumeMessage implements FiberMessage { + + private final RubyThread thread; + private final RubyFiber sendingFiber; + private final Object arg; + + public FiberResumeMessage(RubyThread thread, RubyFiber sendingFiber, Object arg) { + this.thread = thread; + this.sendingFiber = sendingFiber; + this.arg = arg; + } + + public RubyThread getThread() { + return thread; + } + + public RubyFiber getSendingFiber() { + return sendingFiber; + } + + public Object getArg() { + return arg; + } + + } + + private class FiberExitMessage implements FiberMessage { + } + + public class FiberExitException extends ControlFlowException { + + private static final long serialVersionUID = 1522270454305076317L; + + } + + private final FiberManager fiberManager; + private final ThreadManager threadManager; + + private BlockingQueue messageQueue = new ArrayBlockingQueue<>(1); + public RubyFiber lastResumedByFiber = null; + + public RubyFiber(RubyClass rubyClass, FiberManager fiberManager, ThreadManager threadManager) { + super(rubyClass); + this.fiberManager = fiberManager; + this.threadManager = threadManager; + } + + public void initialize(RubyProc block) { + final RubyFiber finalFiber = this; + final RubyProc finalBlock = block; + + new Thread(new Runnable() { + + @Override + public void run() { + fiberManager.registerFiber(finalFiber); + + try { + try { + final Object arg = finalFiber.waitForResume(); + final Object result = finalBlock.call(null, arg); + finalFiber.lastResumedByFiber.resume(finalFiber, result); + } catch (FiberExitException e) { + // Naturally exit the thread on catching this + } + } finally { + fiberManager.unregisterFiber(finalFiber); + } + } + + }).start(); + } + + /** + * Send the Java thread that represents this fiber to sleep until it recieves a resume or exit + * message. On entry, assumes that the GIL is not held. On exit, holding the GIL. + */ + public Object waitForResume() { + FiberMessage message = null; + + do { + try { + // TODO(cs) what is a suitable timeout? + message = messageQueue.poll(1, TimeUnit.SECONDS); + } catch (InterruptedException e) { + // Poll again + } + } while (message == null); + + if (message instanceof FiberExitMessage) { + throw new FiberExitException(); + } + + final FiberResumeMessage resumeMessage = (FiberResumeMessage) message; + + threadManager.enterGlobalLock(resumeMessage.getThread()); + + fiberManager.setCurrentFiber(this); + + lastResumedByFiber = resumeMessage.getSendingFiber(); + return resumeMessage.getArg(); + } + + /** + * Send a message to a fiber by posting into a message queue. Doesn't explicitly notify the Java + * thread (although the queue implementation may) and doesn't wait for the message to be + * received. On entry, assumes the the GIL is held. On exit, not holding the GIL. + */ + public void resume(RubyFiber sendingFiber, Object... args) { + Object arg; + + if (args.length == 0) { + arg = NilPlaceholder.INSTANCE; + } else if (args.length == 1) { + arg = args[0]; + } else { + arg = RubyArray.specializedFromObjects(getRubyClass().getContext().getCoreLibrary().getArrayClass(), args); + } + + final RubyThread runningThread = threadManager.leaveGlobalLock(); + + messageQueue.add(new FiberResumeMessage(runningThread, sendingFiber, arg)); + } + + public void shutdown() { + messageQueue.add(new FiberExitMessage()); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyFile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyFile.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import java.io.*; + +import com.oracle.truffle.ruby.runtime.*; + +/** + * Represents the Ruby {@code File} class. + */ +public class RubyFile extends RubyObject { + + private final Reader reader; + private final Writer writer; + + public RubyFile(RubyClass rubyClass, Reader reader, Writer writer) { + super(rubyClass); + this.reader = reader; + this.writer = writer; + } + + public void close() { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + if (writer != null) { + try { + writer.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + public static String expandPath(String fileName) { + // TODO(cs): see the other expandPath + + try { + return new File(fileName).getCanonicalPath(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static String expandPath(String fileName, String dir) { + /* + * TODO(cs): this isn't quite correct - I think we want to collapse .., but we don't want to + * resolve symlinks etc. This might be where we want to start borrowing JRuby's + * implementation, but it looks quite tied to their data structures. + */ + + try { + return new File(dir, fileName).getCanonicalPath(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static RubyFile open(RubyContext context, String fileName, String mode) { + Reader reader; + Writer writer; + + if (mode.equals("rb")) { + try { + reader = new InputStreamReader(new FileInputStream(fileName)); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + + writer = null; + } else if (mode.equals("w")) { + reader = null; + + try { + writer = new OutputStreamWriter(new FileOutputStream(fileName)); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } else { + throw new UnsupportedOperationException(); + } + + final RubyFile file = new RubyFile(context.getCoreLibrary().getFileClass(), reader, writer); + + return file; + } + + public Reader getReader() { + return reader; + } + + public Writer getWriter() { + return writer; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyFixnum.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyFixnum.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import java.math.*; + +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Represents the Ruby {@code Fixnum} class. + */ +public class RubyFixnum extends RubyObject implements Unboxable { + + public static final int MIN_VALUE = Integer.MIN_VALUE; + public static final int MAX_VALUE = Integer.MAX_VALUE; + + public static final BigInteger MIN_VALUE_BIG = BigInteger.valueOf(MIN_VALUE); + public static final BigInteger MAX_VALUE_BIG = BigInteger.valueOf(MAX_VALUE); + + public static final int SIZE = Integer.SIZE; + + private final int value; + + public RubyFixnum(RubyClass fixnumClass, int value) { + super(fixnumClass); + this.value = value; + } + + public int getValue() { + return value; + } + + @Override + public String toString() { + return Integer.toString(value); + } + + @Override + public boolean equals(Object other) { + if (other instanceof Integer) { + return value == (int) other; + } else if (other instanceof RubyFixnum) { + return value == ((RubyFixnum) other).value; + } else if (other instanceof BigInteger) { + return ((BigInteger) other).equals(value); + } else if (other instanceof RubyBignum) { + return ((RubyBignum) other).getValue().equals(value); + } else if (other instanceof Double) { + return value == (double) other; + } else if (other instanceof RubyFloat) { + return value == ((RubyFloat) other).getValue(); + } else { + return super.equals(other); + } + } + + @Override + public int hashCode() { + throw new UnsupportedOperationException(); + } + + public Object unbox() { + return value; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyFloat.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyFloat.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Represents the Ruby {@code Float} class. + */ +public class RubyFloat extends RubyObject implements Unboxable { + + private final double value; + + public RubyFloat(RubyClass floatClass, double value) { + super(floatClass); + this.value = value; + } + + public double getValue() { + return value; + } + + @Override + public String toString() { + return Double.toString(value); + } + + @Override + public boolean equals(Object other) { + if (other instanceof Integer) { + return value == (int) other; + } else if (other instanceof RubyFixnum) { + return value == ((RubyFixnum) other).getValue(); + } else if (other instanceof Double) { + return value == (double) other; + } else if (other instanceof RubyFloat) { + return value == ((RubyFloat) other).value; + } else { + return super.equals(other); + } + } + + @Override + public int hashCode() { + throw new UnsupportedOperationException(); + } + + public Object unbox() { + return value; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyHash.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyHash.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import java.util.*; + +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Represents the Ruby {@code Hash} class. + */ +public class RubyHash extends RubyObject { + + /** + * The class from which we create the object that is {@code Hash}. A subclass of + * {@link RubyClass} so that we can override {@link #newInstance} and allocate a + * {@link RubyHash} rather than a normal {@link RubyBasicObject}. + */ + public static class RubyHashClass extends RubyClass { + + public RubyHashClass(RubyClass objectClass) { + super(null, objectClass, "Hash"); + } + + @Override + public RubyBasicObject newInstance() { + return new RubyHash(this); + } + + } + + public final Map storage = new LinkedHashMap<>(); + @CompilationFinal public RubyProc defaultBlock = null; + + public RubyHash(RubyClass rubyClass, RubyProc defaultBlock) { + super(rubyClass); + initialize(defaultBlock); + } + + public RubyHash(RubyClass rubyClass) { + super(rubyClass); + } + + public void initialize(RubyProc setDefaultBlock) { + defaultBlock = setDefaultBlock; + } + + @Override + public Object dup() { + final RubyHash newHash = new RubyHash(rubyClass); + newHash.setInstanceVariables(getInstanceVariables()); + newHash.storage.putAll(storage); + return newHash; + } + + public void put(Object key, Object value) { + checkFrozen(); + + storage.put(key, value); + } + + public Object get(Object key) { + return storage.get(key); + } + + public Map getMap() { + return storage; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("{"); + + for (Map.Entry entry : storage.entrySet()) { + if (builder.length() > 1) { + builder.append(", "); + } + + builder.append(entry.getKey().toString()); + builder.append("=>"); + builder.append(entry.getValue().toString()); + } + + builder.append("}"); + return builder.toString(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((storage == null) ? 0 : storage.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof RubyHash)) { + return false; + } + RubyHash other = (RubyHash) obj; + if (storage == null) { + if (other.storage != null) { + return false; + } + } else if (!storage.equals(other.storage)) { + return false; + } + return true; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyMatchData.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyMatchData.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +/** + * Represents the Ruby {@code MatchData} class. + */ +public class RubyMatchData extends RubyObject { + + private final Object[] values; + + public RubyMatchData(RubyClass rubyClass, Object[] values) { + super(rubyClass); + this.values = values; + } + + public Object[] valuesAt(int... indices) { + final Object[] result = new Object[indices.length]; + + for (int n = 0; n < indices.length; n++) { + result[n] = values[indices[n]]; + } + + return result; + } + + public Object[] getValues() { + return values; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyModule.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyModule.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,381 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.utilities.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.lookup.*; +import com.oracle.truffle.ruby.runtime.methods.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Represents the Ruby {@code Module} class. + */ +public class RubyModule extends RubyObject implements LookupNode { + + /** + * The class from which we create the object that is {@code Module}. A subclass of + * {@link RubyClass} so that we can override {@link #newInstance} and allocate a + * {@link RubyModule} rather than a normal {@link RubyBasicObject}. + */ + public static class RubyModuleClass extends RubyClass { + + public RubyModuleClass(RubyContext context) { + super(context, null, null, null, "Module"); + } + + @Override + public RubyBasicObject newInstance() { + return new RubyModule(this, null, "(unnamed module)"); + } + + } + + /** + * The slot within a module definition method frame where we store the implicit state that is + * the current visibility for new methods. + */ + public static final Object VISIBILITY_FRAME_SLOT_ID = new Object(); + + /** + * The slot within a module definition method frame where we store the implicit state that is + * the flag for whether or not new methods will be module methods (functions is the term). + */ + public static final Object MODULE_FUNCTION_FLAG_FRAME_SLOT_ID = new Object(); + + // The context is stored here - objects can obtain it via their class (which is a module) + private final RubyContext context; + + /* + * The module in which this module was defined. By analogy, if superclass is the dynamic scope, + * the parent module is the lexical scope. + */ + private final RubyModule parentModule; + + /* + * The first thing to lookup names in. Not always the class, as we also have singleton classes, + * included modules etc. + */ + private LookupNode lookupParent = LookupTerminal.INSTANCE; + + private final String name; + private final Map methods = new HashMap<>(); + private final Map constants = new HashMap<>(); + private final Map classVariables = new HashMap<>(); + + private final CyclicAssumption unmodifiedAssumption; + + /** + * Keep track of other modules that depend on the configuration of this module in some way. The + * include subclasses and modules that include this module. + */ + private final Set dependents = Collections.newSetFromMap(new WeakHashMap()); + + public RubyModule(RubyClass rubyClass, RubyModule parentModule, String name) { + this(rubyClass.getContext(), rubyClass, parentModule, name); + } + + public RubyModule(RubyContext context, RubyClass rubyClass, RubyModule parentModule, String name) { + super(rubyClass); + + this.context = context; + this.parentModule = parentModule; + this.name = name; + + unmodifiedAssumption = new CyclicAssumption(name + " is unmodified"); + + /* + * Modules always go into the object space manager. Manually allocate an objectID, because + * the lazy mechanism uses the Ruby class of the object, which may not be set yet during + * bootstrap. + */ + + objectID = context.getNextObjectID(); + context.getObjectSpaceManager().add(this); + } + + public RubyModule getParentModule() { + return parentModule; + } + + public void include(RubyModule module) { + checkFrozen(); + + lookupParent = new LookupFork(module, lookupParent); + newVersion(); + module.addDependent(this); + } + + /** + * Set the value of a constant, possibly redefining it. + */ + public void setConstant(String constantName, Object value) { + assert RubyContext.shouldObjectBeVisible(value); + + checkFrozen(); + + getConstants().put(constantName, value); + newVersion(); + // TODO(CS): warn when redefining a constant + } + + public void setClassVariable(String variableName, Object value) { + assert RubyContext.shouldObjectBeVisible(value); + + checkFrozen(); + + if (!setClassVariableIfAlreadySet(variableName, value)) { + classVariables.put(variableName, value); + } + } + + public boolean setClassVariableIfAlreadySet(String variableName, Object value) { + assert RubyContext.shouldObjectBeVisible(value); + + checkFrozen(); + + if (lookupParent.setClassVariableIfAlreadySet(variableName, value)) { + return true; + } + + if (classVariables.containsKey(variableName)) { + classVariables.put(variableName, value); + return true; + } + + return false; + } + + public void removeClassVariable(String variableName) { + checkFrozen(); + + classVariables.remove(variableName); + } + + public void setModuleConstant(String constantName, Object value) { + checkFrozen(); + + setConstant(constantName, value); + getSingletonClass().setConstant(constantName, value); + } + + public void addMethod(RubyMethod method) { + checkFrozen(); + getMethods().put(method.getName(), method); + newVersion(); + } + + /** + * Remove a method from this module. + */ + public void removeMethod(String methodName) { + checkFrozen(); + + getMethods().remove(methodName); + newVersion(); + } + + public void undefMethod(String methodName) { + undefMethod(lookupMethod(methodName)); + } + + public void undefMethod(RubyMethod method) { + addMethod(method.undefined()); + } + + /** + * Alias a method. + */ + public void alias(String newName, String oldName) { + final RubyMethod method = lookupMethod(oldName); + + if (method == null) { + CompilerDirectives.transferToInterpreter(); + throw new RuntimeException("Couldn't alias as coudln't find " + oldName); + } + + addMethod(method.withNewName(newName)); + } + + @Override + public Object lookupConstant(String constantName) { + Object value; + + // Look in this module + + value = getConstants().get(constantName); + + if (value != null) { + return value; + } + + // Look in the parent module + + if (parentModule != null) { + value = parentModule.lookupConstant(constantName); + + if (value != null) { + return value; + } + } + + // Look in the lookup parent + + return lookupParent.lookupConstant(constantName); + } + + @Override + public Object lookupClassVariable(String variableName) { + // Look in this module + + final Object value = classVariables.get(variableName); + + if (value != null) { + return value; + } + + // Look in the parent + + return lookupParent.lookupClassVariable(variableName); + } + + public Set getClassVariables() { + final Set classVariablesSet = new HashSet<>(); + + classVariablesSet.addAll(classVariables.keySet()); + classVariablesSet.addAll(lookupParent.getClassVariables()); + + return classVariablesSet; + } + + @Override + public RubyMethod lookupMethod(String methodName) { + // Look in this module + + final RubyMethod method = getMethods().get(methodName); + + if (method != null) { + return method; + } + + // Look in the parent + + return lookupParent.lookupMethod(methodName); + } + + public void appendFeatures(RubyModule other) { + // TODO(CS): check only run once + + for (Map.Entry constantEntry : getConstants().entrySet()) { + final String constantName = constantEntry.getKey(); + final Object constantValue = constantEntry.getValue(); + other.setModuleConstant(constantName, constantValue); + } + + for (Map.Entry methodEntry : getMethods().entrySet()) { + final String methodName = methodEntry.getKey(); + final RubyMethod method = methodEntry.getValue(); + other.addMethod(method.withNewName(methodName)); + } + } + + public RubyContext getContext() { + return context; + } + + public String getName() { + return name; + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public String toString() { + return name; + } + + public void newVersion() { + unmodifiedAssumption.invalidate(); + + // Make dependents new versions + + for (RubyModule dependent : dependents) { + dependent.newVersion(); + } + } + + public void addDependent(RubyModule dependent) { + dependents.add(dependent); + } + + public Assumption getUnmodifiedAssumption() { + return unmodifiedAssumption.getAssumption(); + } + + public void getMethods(Map foundMethods) { + lookupParent.getMethods(foundMethods); + + for (RubyMethod method : methods.values()) { + foundMethods.put(method.getName(), method); + } + } + + public static void setCurrentVisibility(Frame frame, Visibility visibility) { + final FrameSlot slot = frame.getFrameDescriptor().findFrameSlot(VISIBILITY_FRAME_SLOT_ID); + + frame.setObject(slot, visibility); + } + + public void visibilityMethod(PackedFrame frame, Object[] arguments, Visibility visibility) { + if (arguments.length == 0) { + setCurrentVisibility(frame.unpack(), visibility); + } else { + for (Object arg : arguments) { + final RubyMethod method = lookupMethod(arg.toString()); + + if (method == null) { + throw new RuntimeException("Couldn't find method " + arg.toString()); + } + + /* + * If the method was already defined in this class, that's fine {@link addMethod} + * will overwrite it, otherwise we do actually want to add a copy of the method with + * a different visibility to this module. + */ + + addMethod(method.withNewVisibility(visibility)); + } + } + } + + public List getDeclaredMethods() { + return new ArrayList<>(getMethods().values()); + } + + public void moduleEval(String source) { + getRubyClass().getContext().eval(source, this); + } + + public Map getConstants() { + return constants; + } + + public Map getMethods() { + return methods; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyNilClass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyNilClass.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import com.oracle.truffle.ruby.runtime.*; + +/** + * Represents the Ruby {@code NilClass} class. + */ +public class RubyNilClass extends RubyObject { + + public RubyNilClass(RubyClass rubyClass) { + super(rubyClass); + } + + @Override + public boolean equals(Object other) { + return other instanceof RubyNilClass || other instanceof NilPlaceholder; + } + + @Override + public int hashCode() { + return 0; + } + + public static boolean isNil(Object block) { + return block instanceof NilPlaceholder || block instanceof RubyNilClass; + } + + @Override + public String toString() { + return ""; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyObject.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyObject.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Represents the Ruby {@code Object} class. + */ +public class RubyObject extends RubyBasicObject { + + public boolean frozen = false; + + public RubyObject(RubyClass rubyClass) { + super(rubyClass); + } + + public void checkFrozen() { + if (frozen) { + CompilerDirectives.transferToInterpreter(); + throw new RaiseException(getRubyClass().getContext().getCoreLibrary().frozenError(getRubyClass().getName().toLowerCase())); + } + } + + public Object dup() { + final RubyObject newObject = new RubyObject(rubyClass); + newObject.setInstanceVariables(getInstanceVariables()); + return newObject; + } + + public static String checkInstanceVariableName(RubyContext context, String name) { + if (!name.startsWith("@")) { + throw new RaiseException(context.getCoreLibrary().nameErrorInstanceNameNotAllowable(name)); + } + + return name.substring(1); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyProc.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyProc.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; +import com.oracle.truffle.ruby.runtime.methods.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Represents the Ruby {@code Proc} class. + */ +public class RubyProc extends RubyObject { + + /** + * The class from which we create the object that is {@code Proc}. A subclass of + * {@link RubyClass} so that we can override {@link #newInstance} and allocate a + * {@link RubyProc} rather than a normal {@link RubyBasicObject}. + */ + public static class RubyProcClass extends RubyClass { + + public RubyProcClass(RubyClass objectClass) { + super(null, objectClass, "Proc"); + } + + @Override + public RubyBasicObject newInstance() { + return new RubyProc(this); + } + + } + + public static enum Type { + PROC, LAMBDA + } + + @CompilationFinal private Type type; + @CompilationFinal private Object self; + @CompilationFinal private RubyProc block; + @CompilationFinal private RubyMethod method; + + public RubyProc(RubyClass procClass) { + super(procClass); + } + + public RubyProc(RubyClass procClass, Type type, Object self, RubyProc block, RubyMethod method) { + super(procClass); + initialize(type, self, block, method); + } + + public void initialize(Type setType, Object setSelf, RubyProc setBlock, RubyMethod setMethod) { + assert setSelf != null; + assert RubyContext.shouldObjectBeVisible(setSelf); + type = setType; + self = setSelf; + block = setBlock; + method = setMethod; + } + + public Object getSelf() { + return self; + } + + @CompilerDirectives.SlowPath + public Object call(PackedFrame caller, Object... args) { + return callWithModifiedSelf(caller, self, args); + } + + public Object callWithModifiedSelf(PackedFrame caller, Object modifiedSelf, Object... args) { + assert modifiedSelf != null; + + try { + return method.call(caller, modifiedSelf, block, args); + } catch (ReturnException e) { + switch (type) { + case PROC: + throw e; + case LAMBDA: + return e.getValue(); + default: + throw new IllegalStateException(); + } + } + } + + public RubyMethod getMethod() { + return method; + } + + public Type getType() { + return type; + } + + public RubyProc getBlock() { + return block; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyRegexp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyRegexp.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import java.util.regex.*; + +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Represents the Ruby {@code Regexp} class. + */ +public class RubyRegexp extends RubyObject { + + /** + * The class from which we create the object that is {@code Regexp}. A subclass of + * {@link RubyClass} so that we can override {@link #newInstance} and allocate a + * {@link RubyRegexp} rather than a normal {@link RubyBasicObject}. + */ + public static class RubyRegexpClass extends RubyClass { + + public RubyRegexpClass(RubyClass objectClass) { + super(null, objectClass, "Regexp"); + } + + @Override + public RubyBasicObject newInstance() { + return new RubyRegexp(getContext().getCoreLibrary().getRegexpClass()); + } + + } + + @CompilationFinal private Pattern pattern; + + public RubyRegexp(RubyClass regexpClass) { + super(regexpClass); + } + + public RubyRegexp(RubyClass regexpClass, String pattern) { + this(regexpClass); + initialize(compile(pattern)); + } + + public RubyRegexp(RubyClass regexpClass, Pattern pattern) { + this(regexpClass); + initialize(pattern); + } + + public void initialize(String setPattern) { + pattern = compile(setPattern); + } + + public void initialize(Pattern setPattern) { + pattern = setPattern; + } + + public Object matchOperator(Frame frame, String string) { + final RubyContext context = getRubyClass().getContext(); + + final Matcher matcher = pattern.matcher(string); + + if (matcher.find()) { + for (int n = 1; n < matcher.groupCount() + 1; n++) { + final FrameSlot slot = frame.getFrameDescriptor().findFrameSlot("$" + n); + + if (slot != null) { + frame.setObject(slot, context.makeString(matcher.group(n))); + } + } + + return matcher.start(); + } else { + return NilPlaceholder.INSTANCE; + } + } + + public Pattern getPattern() { + return pattern; + } + + public Object match(String string) { + final RubyContext context = getRubyClass().getContext(); + + final Matcher matcher = pattern.matcher(string); + + if (!matcher.find()) { + return NilPlaceholder.INSTANCE; + } + + final Object[] values = new Object[matcher.groupCount() + 1]; + + for (int n = 0; n < matcher.groupCount() + 1; n++) { + final String group = matcher.group(n); + + if (group == null) { + values[n] = NilPlaceholder.INSTANCE; + } else { + values[n] = context.makeString(group); + } + } + + return new RubyMatchData(context.getCoreLibrary().getMatchDataClass(), values); + } + + @Override + public int hashCode() { + return pattern.pattern().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof RubyRegexp)) { + return false; + } + RubyRegexp other = (RubyRegexp) obj; + if (pattern == null) { + if (other.pattern != null) { + return false; + } + } else if (!pattern.pattern().equals(other.pattern.pattern())) { + return false; + } + return true; + } + + public static Pattern compile(String pattern) { + return Pattern.compile(pattern, Pattern.MULTILINE | Pattern.UNIX_LINES); + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyString.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyString.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import java.math.*; +import java.nio.*; +import java.nio.charset.*; +import java.util.*; +import java.util.regex.*; + +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.array.*; +import com.oracle.truffle.ruby.runtime.core.range.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Represents the Ruby {@code String} class. + */ +public class RubyString extends RubyObject { + + /** + * The class from which we create the object that is {@code String}. A subclass of + * {@link RubyClass} so that we can override {@link #newInstance} and allocate a + * {@link RubyString} rather than a normal {@link RubyBasicObject}. + */ + public static class RubyStringClass extends RubyClass { + + public RubyStringClass(RubyClass objectClass) { + super(null, objectClass, "String"); + } + + @Override + public RubyBasicObject newInstance() { + return new RubyString(getContext().getCoreLibrary().getStringClass(), ""); + } + + } + + private boolean fromJavaString; + + private Charset encoding; + private byte[] bytes; + + private String cachedStringValue; + + /** + * Construct a string from a Java {@link String}, lazily converting to bytes as needed. + */ + public RubyString(RubyClass stringClass, String value) { + super(stringClass); + fromJavaString = true; + encoding = null; + bytes = null; + cachedStringValue = value; + } + + /** + * Construct a string from bytes representing characters in an encoding, lazily converting to a + * Java {@link String} as needed. + */ + public RubyString(RubyClass stringClass, Charset encoding, byte[] bytes) { + super(stringClass); + fromJavaString = false; + this.encoding = encoding; + this.bytes = bytes; + cachedStringValue = null; + } + + public RubyString(RubyString copyOf) { + super(copyOf.getRubyClass().getContext().getCoreLibrary().getStringClass()); + fromJavaString = copyOf.fromJavaString; + encoding = copyOf.encoding; + + if (copyOf.bytes != null) { + bytes = Arrays.copyOf(copyOf.bytes, copyOf.bytes.length); + } else { + bytes = null; + } + + cachedStringValue = copyOf.cachedStringValue; + } + + public boolean isFromJavaString() { + return fromJavaString; + } + + public byte[] getBytes() { + return bytes; + } + + public void replace(String value) { + fromJavaString = true; + encoding = null; + bytes = null; + cachedStringValue = value; + } + + @Override + public String toString() { + if (cachedStringValue == null) { + cachedStringValue = encoding.decode(ByteBuffer.wrap(bytes)).toString(); + } + + return cachedStringValue; + } + + @Override + public boolean equals(Object other) { + if (other == null) { + return false; + } + + // If the other value is a Java string, use our Java string representation to compare + + if (other instanceof String) { + return toString().equals(other); + } + + if (other instanceof RubyString) { + final RubyString otherString = (RubyString) other; + + // If we both came from Java strings, use them to compare + + if (fromJavaString && otherString.fromJavaString) { + return toString().equals(other.toString()); + } + + // If we both have the same encoding, compare bytes + + if (encoding == otherString.encoding) { + return Arrays.equals(bytes, otherString.bytes); + } + + // If we don't have the same encoding, we need some more advanced logic + + throw new UnsupportedOperationException("Can't compare strings in different encodings yet"); + } + + return false; + } + + @Override + public int hashCode() { + return toString().hashCode(); + } + + public static Object getIndex(RubyContext context, String string, Object[] args) { + if (args.length == 1) { + final Object index = args[0]; + + if (index instanceof Integer) { + final int stringLength = string.length(); + final int normalisedIndex = ArrayUtilities.normaliseIndex(stringLength, (int) index); + + return context.makeString(string.charAt(normalisedIndex)); + } else if (index instanceof FixnumRange) { + final FixnumRange range = (FixnumRange) index; + + final int stringLength = string.length(); + + if (range.doesExcludeEnd()) { + final int begin = ArrayUtilities.normaliseIndex(stringLength, range.getBegin()); + final int exclusiveEnd = ArrayUtilities.normaliseExclusiveIndex(stringLength, range.getExclusiveEnd()); + return context.makeString(string.substring(begin, exclusiveEnd)); + } else { + final int begin = ArrayUtilities.normaliseIndex(stringLength, range.getBegin()); + final int inclusiveEnd = ArrayUtilities.normaliseIndex(stringLength, range.getInclusiveEnd()); + return context.makeString(string.substring(begin, inclusiveEnd + 1)); + } + } else { + throw new UnsupportedOperationException("Don't know how to index a string with " + index.getClass()); + } + } else { + final int rangeStart = (int) args[0]; + int rangeLength = (int) args[1]; + + if (rangeLength > string.length() - rangeStart) { + rangeLength = string.length() - rangeStart; + } + + if (rangeStart > string.length()) { + return NilPlaceholder.INSTANCE; + } + + return context.makeString(string.substring(rangeStart, rangeStart + rangeLength)); + } + } + + @Override + public Object dup() { + return new RubyString(this); + } + + public void concat(RubyString other) { + if (fromJavaString && other.fromJavaString) { + cachedStringValue += other.cachedStringValue; + encoding = null; + bytes = null; + } else { + throw new UnsupportedOperationException("Don't know how to append strings with encodings"); + } + } + + public static String ljust(String string, int length, String padding) { + final StringBuilder builder = new StringBuilder(); + + builder.append(string); + + int n = 0; + + while (builder.length() < length) { + builder.append(padding.charAt(n)); + + n++; + + if (n == padding.length()) { + n = 0; + } + } + + return builder.toString(); + } + + public static String rjust(String string, int length, String padding) { + final StringBuilder builder = new StringBuilder(); + + int n = 0; + + while (builder.length() + string.length() < length) { + builder.append(padding.charAt(n)); + + n++; + + if (n == padding.length()) { + n = 0; + } + } + + builder.append(string); + + return builder.toString(); + } + + public static RubyArray scan(RubyContext context, String string, Pattern pattern) { + final Matcher matcher = pattern.matcher(string); + + final RubyArray results = new RubyArray(context.getCoreLibrary().getArrayClass()); + + while (matcher.find()) { + if (matcher.groupCount() == 0) { + results.push(context.makeString(matcher.group(0))); + } else { + final RubyArray subResults = new RubyArray(context.getCoreLibrary().getArrayClass()); + + for (int n = 1; n < matcher.groupCount() + 1; n++) { + subResults.push(context.makeString(matcher.group(n))); + } + + results.push(subResults); + } + } + + return results; + } + + public Object toInteger() { + if (toString().length() == 0) { + return 0; + } + + try { + final int value = Integer.parseInt(toString()); + + if (value >= RubyFixnum.MIN_VALUE && value <= RubyFixnum.MAX_VALUE) { + return value; + } else { + return BigInteger.valueOf(value); + } + } catch (NumberFormatException e) { + return new BigInteger(toString()); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubySymbol.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubySymbol.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.methods.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Represents the Ruby {@code Symbol} class. + */ +public class RubySymbol extends RubyObject { + + private final String symbol; + + public RubySymbol(RubyClass symbolClass, String symbol) { + super(symbolClass); + this.symbol = symbol.intern(); + } + + public RubyProc toProc() { + final RubyContext context = getRubyClass().getContext(); + + final CallTarget callTarget = new CallTarget() { + + @Override + public Object call(PackedFrame frame, Arguments args) { + final RubyArguments rubyArgs = (RubyArguments) args; + final Object receiver = rubyArgs.getArguments()[0]; + final Object[] sendArgs = Arrays.copyOfRange(rubyArgs.getArguments(), 1, rubyArgs.getArguments().length); + final RubyBasicObject receiverObject = context.getCoreLibrary().box(receiver); + return receiverObject.send(symbol, rubyArgs.getBlock(), sendArgs); + } + + }; + + final CallTargetMethodImplementation methodImplementation = new CallTargetMethodImplementation(callTarget, null); + final RubyMethod method = new RubyMethod(null, null, new UniqueMethodIdentifier(), symbol, null, Visibility.PUBLIC, false, methodImplementation); + + return new RubyProc(context.getCoreLibrary().getProcClass(), RubyProc.Type.PROC, NilPlaceholder.INSTANCE, null, method); + } + + @Override + public String toString() { + return symbol; + } + + @Override + public String inspect() { + return ":" + symbol; + } + + @Override + public int hashCode() { + return symbol.hashCode(); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } else if (other instanceof RubySymbol) { + return symbol == ((RubySymbol) other).symbol; + } else if (other instanceof RubyString) { + return other.equals(symbol); + } else { + return super.equals(other); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyThread.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyThread.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import java.util.*; +import java.util.concurrent.*; + +import com.oracle.truffle.ruby.runtime.objects.*; +import com.oracle.truffle.ruby.runtime.subsystems.*; + +/** + * Represents the Ruby {@code Thread} class. Implemented using Java threads, but note that there is + * not a one-to-one mapping between Ruby threads and Java threads - specifically in combination with + * fibers as they are currently implemented as their own Java threads. + */ +public class RubyThread extends RubyObject { + + /** + * The class from which we create the object that is {@code Thread}. A subclass of + * {@link RubyClass} so that we can override {@link #newInstance} and allocate a + * {@link RubyThread} rather than a normal {@link RubyBasicObject}. + */ + public static class RubyThreadClass extends RubyClass { + + public RubyThreadClass(RubyClass objectClass) { + super(null, objectClass, "Thread"); + } + + @Override + public RubyBasicObject newInstance() { + return new RubyThread(this, getContext().getThreadManager()); + } + + } + + private final ThreadManager manager; + + private final CountDownLatch finished = new CountDownLatch(1); + + private final int hashCode = new Random().nextInt(); + + public RubyThread(RubyClass rubyClass, ThreadManager manager) { + super(rubyClass); + this.manager = manager; + } + + public void initialize(RubyProc block) { + final RubyProc finalBlock = block; + + initialize(new Runnable() { + + @Override + public void run() { + finalBlock.call(null); + } + + }); + } + + public void initialize(Runnable runnable) { + final RubyThread finalThread = this; + final Runnable finalRunnable = runnable; + + new Thread(new Runnable() { + + @Override + public void run() { + finalThread.manager.registerThread(finalThread); + finalThread.manager.enterGlobalLock(finalThread); + + try { + finalRunnable.run(); + } finally { + finalThread.manager.leaveGlobalLock(); + finalThread.manager.unregisterThread(finalThread); + finalThread.finished.countDown(); + } + } + + }).start(); + } + + @Override + public int hashCode() { + return hashCode; + } + + public void shutdown() { + } + + public void join() { + final RubyThread runningThread = getRubyClass().getContext().getThreadManager().leaveGlobalLock(); + + try { + while (true) { + try { + finished.await(); + break; + } catch (InterruptedException e) { + // Await again + } + } + } finally { + runningThread.manager.enterGlobalLock(runningThread); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyTime.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyTime.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import java.text.*; +import java.util.*; + +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Represents the Ruby {@code Time} class. This is a very rough implementation and is only really + * enough to run benchmark harnesses. + */ +public class RubyTime extends RubyObject { + + /** + * The class from which we create the object that is {@code Time}. A subclass of + * {@link RubyClass} so that we can override {@link #newInstance} and allocate a + * {@link RubyTime} rather than a normal {@link RubyBasicObject}. + */ + public static class RubyTimeClass extends RubyClass { + + public RubyTimeClass(RubyClass objectClass) { + super(null, objectClass, "Time"); + } + + @Override + public RubyBasicObject newInstance() { + return new RubyTime(this, milisecondsToNanoseconds(System.currentTimeMillis())); + } + + } + + private final long nanoseconds; + + public RubyTime(RubyClass timeClass, long nanoseconds) { + super(timeClass); + this.nanoseconds = nanoseconds; + } + + /** + * Subtract one time from another, producing duration in seconds. + */ + public double subtract(RubyTime other) { + return nanosecondsToSecond(nanoseconds - other.nanoseconds); + } + + @Override + public String toString() { + /* + * I think this is ISO 8601 with a custom time part. Note that Ruby's time formatting syntax + * is different to Java's. + */ + + return new SimpleDateFormat("Y-MM-d H:m:ss Z").format(toDate()); + } + + private Date toDate() { + return new Date(nanosecondsToMiliseconds(nanoseconds)); + } + + public static RubyTime fromDate(RubyClass timeClass, long timeMiliseconds) { + return new RubyTime(timeClass, milisecondsToNanoseconds(timeMiliseconds)); + } + + private static long milisecondsToNanoseconds(long miliseconds) { + return miliseconds * 1000000; + } + + private static long nanosecondsToMiliseconds(long nanoseconds) { + return nanoseconds / 1000000; + } + + private static double nanosecondsToSecond(long nanoseconds) { + return nanoseconds / 1e9; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyTrueClass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/RubyTrueClass.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Represents the Ruby {@code TrueClass} class. + */ +public class RubyTrueClass extends RubyObject implements Unboxable { + + public RubyTrueClass(RubyClass objectClass) { + super(objectClass); + } + + public Object unbox() { + return true; + } + + @Override + public String toString() { + return "true"; + } + + @Override + public boolean equals(Object other) { + return other instanceof RubyTrueClass || (other instanceof Boolean && (boolean) other); + } + + @Override + public int hashCode() { + return Boolean.TRUE.hashCode(); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/StringFormatter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/StringFormatter.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core; + +import java.io.*; +import java.util.*; + +import com.oracle.truffle.ruby.runtime.core.array.*; + +public class StringFormatter { + + public static String format(String format, List values) { + final ByteArrayOutputStream byteArray = new ByteArrayOutputStream(); + final PrintStream printStream = new PrintStream(byteArray); + + format(printStream, format, values); + + return byteArray.toString(); + } + + public static void format(PrintStream stream, String format, List values) { + /* + * See http://www.ruby-doc.org/core-1.9.3/Kernel.html#method-i-sprintf. + * + * At the moment we just do the basics that we need. We will need a proper lexer later on. + * Or better than that we could compile to Truffle nodes if the format string is constant! I + * don't think we can easily translate to Java's format syntax, otherwise JRuby would do + * that and they don't. + */ + + // I'm not using a for loop, because Checkstyle won't let me modify the control variable + + int n = 0; + int v = 0; + + while (n < format.length()) { + final char c = format.charAt(n); + n++; + + if (c == '%') { + // %[flags][width][.precision]type + + final String flagChars = "0"; + + boolean zeroPad = false; + + while (n < format.length() && flagChars.indexOf(format.charAt(n)) != -1) { + switch (format.charAt(n)) { + case '0': + zeroPad = true; + break; + } + + n++; + } + + int width; + + if (n < format.length() && Character.isDigit(format.charAt(n))) { + final int widthStart = n; + + while (Character.isDigit(format.charAt(n))) { + n++; + } + + width = Integer.parseInt(format.substring(widthStart, n)); + } else { + width = 0; + } + + int precision; + + if (format.charAt(n) == '.') { + n++; + + final int precisionStart = n; + + while (Character.isDigit(format.charAt(n))) { + n++; + } + + precision = Integer.parseInt(format.substring(precisionStart, n)); + } else { + precision = 5; + } + + final char type = format.charAt(n); + n++; + + final StringBuilder formatBuilder = new StringBuilder(); + + formatBuilder.append("%"); + + if (width > 0) { + if (zeroPad) { + formatBuilder.append("0"); + } + + formatBuilder.append(width); + } + + switch (type) { + case 'd': { + formatBuilder.append("d"); + final int value = GeneralConversions.toFixnum(values.get(v)); + stream.printf(formatBuilder.toString(), value); + break; + } + + case 'f': { + formatBuilder.append("."); + formatBuilder.append(precision); + formatBuilder.append("f"); + final double value = GeneralConversions.toFloat(values.get(v)); + stream.printf(formatBuilder.toString(), value); + break; + } + + default: + throw new RuntimeException("Kernel#sprintf error"); + } + + v++; + } else { + stream.print(c); + } + } + } + + public static void formatPuts(PrintStream stream, List args) { + if (args.size() > 0) { + formatPutsInner(stream, args); + } else { + stream.println(); + } + } + + public static void formatPutsInner(PrintStream stream, List args) { + if (args.size() > 0) { + for (Object arg : args) { + if (arg instanceof RubyArray) { + final RubyArray array = (RubyArray) arg; + formatPutsInner(stream, array.asList()); + } else { + stream.println(arg); + } + } + } + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/ArrayStore.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/ArrayStore.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core.array; + +/** + * Interface to various ways to store values in arrays. + */ +public interface ArrayStore { + + /** + * Get the size of the store. + */ + int size(); + + /** + * Get a value from the array using a normalized index. + */ + Object get(int normalisedIndex); + + /** + * Get a range of values from an array store. + */ + ArrayStore getRange(int normalisedBegin, int truncatedNormalisedExclusiveEnd); + + /** + * Set a value at an index, or throw {@link GeneraliseArrayStoreException} if that's not + * possible. + */ + void set(int normalisedIndex, Object value) throws GeneraliseArrayStoreException; + + /** + * Set a range to be a single value, or throw {@link GeneraliseArrayStoreException} if that's + * not possible. + */ + void setRangeSingle(int normalisedBegin, int truncatedNormalisedExclusiveEnd, Object value) throws GeneraliseArrayStoreException; + + /** + * Set a range to be a copied from another array, or throw {@link GeneraliseArrayStoreException} + * if that's not possible. + */ + void setRangeArray(int normalisedBegin, int normalisedExclusiveEnd, ArrayStore other) throws GeneraliseArrayStoreException; + + /** + * Insert a value at an index, or throw {@link GeneraliseArrayStoreException} if that's not + * possible. + */ + void insert(int normalisedIndex, Object value) throws GeneraliseArrayStoreException; + + /** + * Push a value onto the end, or throw {@link GeneraliseArrayStoreException} if that's not + * possible. + */ + void push(Object value) throws GeneraliseArrayStoreException; + + /** + * Delete a value at an index, returning the value. + */ + Object deleteAt(int normalisedIndex); + + /** + * Does a store contain a value? + */ + boolean contains(Object value); + + /** + * Duplicate the store. + */ + ArrayStore dup(); + + /** + * Duplicate the store, in a format which can store an object. + */ + ArrayStore generalizeFor(Object type); + + /** + * Get the type of value stored. + */ + Object getIndicativeValue(); + + /** + * Get the contents of the store as a new array. + */ + Object[] toObjectArray(); + + /** + * Does one store equal another. + */ + boolean equals(ArrayStore other); + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/ArrayUtilities.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/ArrayUtilities.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core.array; + +/** + * Simple array utilities, not tied to any particular implementation. + */ +public abstract class ArrayUtilities { + + /** + * Apply Ruby's wrap-around index semantics. + */ + public static int normaliseIndex(int length, int index) { + if (index < 0) { + return length + index; + } else { + return index; + } + } + + /** + * Apply Ruby's wrap-around index semantics. + */ + public static int normaliseExclusiveIndex(int length, int exclusiveIndex) { + if (exclusiveIndex < 0) { + return length + exclusiveIndex + 1; + } else { + return exclusiveIndex; + } + } + + /** + * If an exclusive index is beyond the end of the array, truncate it to be length of the array. + */ + public static int truncateNormalisedExclusiveIndex(int length, int normalisedExclusiveEnd) { + return Math.min(length, normalisedExclusiveEnd); + } + + /** + * What capacity should we allocate for a given requested length? + */ + public static int capacityFor(int length) { + return Math.max(16, length * 2); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/BaseArrayStore.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/BaseArrayStore.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core.array; + +/** + * Contains implementations of as much of the array stores that we could easily share. Much of the + * rest depends on static types in method signatures, so is lexically almost the same, but isn't the + * same in type, and as the whole point is to avoid boxing, we can't use Java's generics. + */ +public abstract class BaseArrayStore implements ArrayStore { + + protected int capacity; + protected int size; + + @Override + public int size() { + return size; + } + + /** + * Set a range in the array to be another range. You must ensure that the otherValues array is + * of the same type as your values array. + */ + protected void setRangeArrayMatchingTypes(int normalisedBegin, int normalisedExclusiveEnd, Object otherValues, int otherSize) { + // Is the range the whole array? + + if (normalisedBegin == 0 && normalisedExclusiveEnd == size) { + // Do we already have enough space? + + if (otherSize <= capacity) { + // Copy to our existing array. + final Object values = getValuesArrayObject(); + System.arraycopy(otherValues, 0, values, 0, otherSize); + } else { + // Create a new copy of their array. + setCapacityWithNewArray(otherSize); + final Object values = getValuesArrayObject(); + System.arraycopy(otherValues, 0, values, 0, otherSize); + } + + size = otherSize; + } else { + final int rangeLength = normalisedExclusiveEnd - normalisedBegin; + + // Create extra space - might be negative if the new range is shorter, or zero. + + final int extraSpaceNeeded = otherSize - rangeLength; + + if (extraSpaceNeeded > 0) { + createSpace(normalisedBegin, extraSpaceNeeded); + } else if (extraSpaceNeeded < 0) { + deleteSpace(normalisedBegin, -extraSpaceNeeded); + } + + // Copy across the new values. + final Object values = getValuesArrayObject(); + System.arraycopy(otherValues, 0, values, normalisedBegin, otherSize); + } + } + + protected void createSpace(int normalisedBegin, int count) { + /* + * Is this space at the end or in the middle? + */ + + if (normalisedBegin == size) { + createSpaceAtEnd(count); + } else { + /* + * Create space in the middle - is the array already big enough? + */ + + final int elementsToMove = size - normalisedBegin; + + if (size + count > capacity) { + /* + * The array isn't big enough. We don't want to use Arrays.copyOf because that will + * do wasted copying of the elements we are about to move. However - is + * Arrays.copyOf clever enough to see that only one instance of Array is using the + * block and use realloc, potentially avoiding a malloc and winning? + */ + + final Object values = getValuesArrayObject(); + setCapacityWithNewArray(ArrayUtilities.capacityFor(size + count)); + final Object newValues = getValuesArrayObject(); + System.arraycopy(values, 0, newValues, 0, normalisedBegin); + System.arraycopy(values, normalisedBegin, newValues, normalisedBegin + count, elementsToMove); + } else { + /* + * The array is already big enough - we can copy elements already in the array to + * make space. + */ + + final Object values = getValuesArrayObject(); + System.arraycopy(values, normalisedBegin, values, normalisedBegin + count, elementsToMove); + } + + size += count; + } + } + + protected void createSpaceAtEnd(int count) { + /* + * Create space at the end - we can do this by creating a copy of the array if needed. + */ + + if (size + count > capacity) { + setCapacityByCopying(ArrayUtilities.capacityFor(size + count)); + } + + size += count; + } + + protected void deleteSpace(int normalisedBegin, int count) { + final Object values = getValuesArrayObject(); + final int elementsToMove = size - normalisedBegin - count; + + if (elementsToMove > 0) { + System.arraycopy(values, normalisedBegin + count, values, normalisedBegin, elementsToMove); + } + + size -= count; + } + + protected abstract void setCapacityByCopying(int newCapacity); + + protected abstract void setCapacityWithNewArray(int newCapacity); + + protected abstract Object getValuesArrayObject(); + + @Override + public boolean equals(ArrayStore other) { + for (int n = 0; n < size; n++) { + if (!other.get(n).equals(get(n))) { + return false; + } + } + + return true; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/EmptyArrayStore.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/EmptyArrayStore.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core.array; + +import com.oracle.truffle.ruby.runtime.*; + +/** + * An array store that can only be empty. + */ +public final class EmptyArrayStore implements ArrayStore { + + public static final EmptyArrayStore INSTANCE = new EmptyArrayStore(); + + private EmptyArrayStore() { + } + + @Override + public int size() { + return 0; + } + + @Override + public Object get(int normalisedIndex) { + return NilPlaceholder.INSTANCE; + } + + @Override + public ArrayStore getRange(int normalisedBegin, int truncatedNormalisedExclusiveEnd) { + return null; // Represents Nil + } + + @Override + public void set(int normalisedIndex, Object value) throws GeneraliseArrayStoreException { + throw new GeneraliseArrayStoreException(); + } + + @Override + public void setRangeSingle(int normalisedBegin, int truncatedNormalisedExclusiveEnd, Object value) throws GeneraliseArrayStoreException { + throw new GeneraliseArrayStoreException(); + } + + @Override + public void setRangeArray(int normalisedBegin, int normalisedExclusiveEnd, ArrayStore other) throws GeneraliseArrayStoreException { + throw new GeneraliseArrayStoreException(); + } + + @Override + public void insert(int normalisedIndex, Object value) throws GeneraliseArrayStoreException { + throw new GeneraliseArrayStoreException(); + } + + @Override + public void push(Object value) throws GeneraliseArrayStoreException { + throw new GeneraliseArrayStoreException(); + } + + @Override + public Object deleteAt(int normalisedIndex) { + throw new UnsupportedOperationException("Cannot delete from an empty array"); + } + + @Override + public ArrayStore dup() { + return this; + } + + @Override + public boolean contains(Object value) { + return false; + } + + @Override + public ArrayStore generalizeFor(Object type) { + if (type instanceof Integer) { + return new FixnumArrayStore(); + } else { + return new ObjectArrayStore(); + } + } + + @Override + public Object getIndicativeValue() { + return null; + } + + @Override + public Object[] toObjectArray() { + return new Object[]{}; + } + + @Override + public boolean equals(ArrayStore other) { + if (other == null) { + return false; + } else if (other == this) { + return true; + } else { + return other.size() == 0; + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/FixnumArrayStore.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/FixnumArrayStore.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core.array; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * A store for an array of Fixnums. + */ +public final class FixnumArrayStore extends BaseArrayStore { + + private int[] values; + + public FixnumArrayStore() { + this(new int[]{}); + } + + public FixnumArrayStore(int[] values) { + this.values = values; + size = values.length; + capacity = values.length; + } + + @Override + public Object get(int normalisedIndex) { + try { + return getFixnum(normalisedIndex); + } catch (UnexpectedResultException e) { + return e.getResult(); + } + } + + public int getFixnum(int normalisedIndex) throws UnexpectedResultException { + if (normalisedIndex >= size) { + throw new UnexpectedResultException(NilPlaceholder.INSTANCE); + } + + return values[normalisedIndex]; + } + + @Override + public ArrayStore getRange(int normalisedBegin, int truncatedNormalisedExclusiveEnd) { + if (normalisedBegin >= size) { + return null; // Represents Nil + } + + return new FixnumArrayStore(Arrays.copyOfRange(values, normalisedBegin, truncatedNormalisedExclusiveEnd)); + } + + @Override + public void set(int normalisedIndex, Object value) throws GeneraliseArrayStoreException { + if (value instanceof Integer) { + setFixnum(normalisedIndex, (int) value); + } else { + throw new GeneraliseArrayStoreException(); + } + } + + public void setFixnum(int normalisedIndex, int value) throws GeneraliseArrayStoreException { + if (normalisedIndex > size) { + throw new GeneraliseArrayStoreException(); + } + + if (normalisedIndex == size) { + push(value); + } else { + values[normalisedIndex] = value; + } + } + + @Override + public void setRangeSingle(int normalisedBegin, int truncatedNormalisedExclusiveEnd, Object value) throws GeneraliseArrayStoreException { + if (value instanceof Integer) { + setRangeSingleFixnum(normalisedBegin, truncatedNormalisedExclusiveEnd, (int) value); + } else { + throw new GeneraliseArrayStoreException(); + } + } + + public void setRangeSingleFixnum(int normalisedBegin, int truncatedNormalisedExclusiveEnd, int value) { + // Is the range the whole array? + + if (normalisedBegin == 0 && truncatedNormalisedExclusiveEnd == size) { + // Reset length and set the value. + size = 1; + values[0] = value; + } else { + // Delete the range, except for the first value. + deleteSpace(normalisedBegin + 1, truncatedNormalisedExclusiveEnd - normalisedBegin - 1); + + // Set the value we left in. + values[normalisedBegin] = value; + } + } + + @Override + public void setRangeArray(int normalisedBegin, int normalisedExclusiveEnd, ArrayStore other) throws GeneraliseArrayStoreException { + if (other instanceof FixnumArrayStore) { + setRangeArrayFixnum(normalisedBegin, normalisedExclusiveEnd, (FixnumArrayStore) other); + } else { + throw new GeneraliseArrayStoreException(); + } + } + + public void setRangeArrayFixnum(int normalisedBegin, int normalisedExclusiveEnd, FixnumArrayStore other) { + setRangeArrayMatchingTypes(normalisedBegin, normalisedExclusiveEnd, other.values, other.size); + } + + @Override + public void insert(int normalisedIndex, Object value) throws GeneraliseArrayStoreException { + if (value instanceof Integer) { + insertFixnum(normalisedIndex, (int) value); + } else { + throw new GeneraliseArrayStoreException(); + } + } + + public void insertFixnum(int normalisedIndex, int value) throws GeneraliseArrayStoreException { + if (normalisedIndex > size) { + throw new GeneraliseArrayStoreException(); + } + + createSpace(normalisedIndex, 1); + values[normalisedIndex] = value; + } + + @Override + public void push(Object value) throws GeneraliseArrayStoreException { + if (value instanceof Integer) { + pushFixnum((int) value); + } else { + throw new GeneraliseArrayStoreException(); + } + } + + public void pushFixnum(int value) { + createSpaceAtEnd(1); + values[size - 1] = value; + } + + @Override + public Object deleteAt(int normalisedIndex) { + try { + return deleteAtFixnum(normalisedIndex); + } catch (UnexpectedResultException e) { + return e.getResult(); + } + } + + public int deleteAtFixnum(int normalisedIndex) throws UnexpectedResultException { + if (normalisedIndex >= size) { + CompilerDirectives.transferToInterpreter(); + throw new UnexpectedResultException(NilPlaceholder.INSTANCE); + } + + final int value = values[normalisedIndex]; + + deleteSpace(normalisedIndex, 1); + + return value; + } + + @Override + public ArrayStore dup() { + return new FixnumArrayStore(Arrays.copyOf(values, size)); + } + + @Override + public boolean contains(Object value) { + if (!(value instanceof Integer)) { + return false; + } + + final int intValue = (int) value; + + for (int n = 0; n < size; n++) { + if (values[n] == intValue) { + return true; + } + } + + return false; + } + + @Override + public ArrayStore generalizeFor(Object type) { + return new ObjectArrayStore(toObjectArray()); + } + + @Override + public Object getIndicativeValue() { + return 0; + } + + @Override + protected void setCapacityByCopying(int newCapacity) { + values = Arrays.copyOf(values, newCapacity); + capacity = values.length; + } + + @Override + protected void setCapacityWithNewArray(int newCapacity) { + values = new int[newCapacity]; + capacity = values.length; + } + + @Override + protected Object getValuesArrayObject() { + return values; + } + + @Override + public Object[] toObjectArray() { + final Object[] objectValues = new Object[size]; + + // System.arraycopy will not box. + + for (int n = 0; n < size; n++) { + objectValues[n] = values[n]; + } + + return objectValues; + } + + @Override + public boolean equals(ArrayStore other) { + if (other instanceof FixnumArrayStore) { + return equals((FixnumArrayStore) other); + } else { + return super.equals(other); + } + } + + public boolean equals(FixnumArrayStore other) { + if (other == null) { + return false; + } else if (other == this) { + return true; + } else if (other.size != size) { + return false; + } else if (other.capacity == capacity) { + return Arrays.equals(other.values, values); + } else { + for (int n = 0; n < size; n++) { + if (other.values[n] != values[n]) { + return false; + } + } + + return true; + } + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/FixnumImmutablePairArrayStore.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/FixnumImmutablePairArrayStore.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core.array; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * A store for a pair of Fixnums. + */ +public final class FixnumImmutablePairArrayStore extends BaseArrayStore { + + private final int first; + private final int second; + + public FixnumImmutablePairArrayStore(int first, int second) { + size = 2; + capacity = 2; + this.first = first; + this.second = second; + } + + @Override + public int size() { + return 2; + } + + @Override + public Object get(int normalisedIndex) { + switch (normalisedIndex) { + case 0: + return first; + case 1: + return second; + default: + return NilPlaceholder.INSTANCE; + } + } + + public int getFixnum(int normalisedIndex) throws UnexpectedResultException { + switch (normalisedIndex) { + case 0: + return first; + case 1: + return second; + default: + CompilerDirectives.transferToInterpreter(); + throw new UnexpectedResultException(NilPlaceholder.INSTANCE); + } + } + + @Override + public ArrayStore getRange(int normalisedBegin, int truncatedNormalisedExclusiveEnd) { + if (normalisedBegin >= size) { + return null; // Represents Nil + } + + return new FixnumArrayStore(Arrays.copyOfRange(new int[]{first, second}, normalisedBegin, truncatedNormalisedExclusiveEnd)); + } + + @Override + public void set(int normalisedIndex, Object value) throws GeneraliseArrayStoreException { + CompilerDirectives.transferToInterpreter(); + throw new GeneraliseArrayStoreException(); + } + + @Override + public void setRangeSingle(int normalisedBegin, int truncatedNormalisedExclusiveEnd, Object value) throws GeneraliseArrayStoreException { + CompilerDirectives.transferToInterpreter(); + throw new GeneraliseArrayStoreException(); + } + + @Override + public void setRangeArray(int normalisedBegin, int normalisedExclusiveEnd, ArrayStore other) throws GeneraliseArrayStoreException { + CompilerDirectives.transferToInterpreter(); + throw new GeneraliseArrayStoreException(); + } + + @Override + public void insert(int normalisedIndex, Object value) throws GeneraliseArrayStoreException { + CompilerDirectives.transferToInterpreter(); + throw new GeneraliseArrayStoreException(); + } + + @Override + public void push(Object value) throws GeneraliseArrayStoreException { + CompilerDirectives.transferToInterpreter(); + throw new GeneraliseArrayStoreException(); + } + + @Override + public Object deleteAt(int normalisedIndex) { + throw new UnsupportedOperationException(); + } + + @Override + public ArrayStore dup() { + return this; + } + + @Override + public boolean contains(Object value) { + if (value instanceof Integer) { + final int intValue = (int) value; + return first == intValue || second == intValue; + } else { + return false; + } + } + + @Override + public ArrayStore generalizeFor(Object type) { + return new ObjectArrayStore(toObjectArray()); + } + + @Override + public Object getIndicativeValue() { + return 0; + } + + @Override + protected void setCapacityByCopying(int newCapacity) { + throw new UnsupportedOperationException(); + } + + @Override + protected void setCapacityWithNewArray(int newCapacity) { + throw new UnsupportedOperationException(); + } + + @Override + protected Object getValuesArrayObject() { + return new int[]{first, second}; + } + + @Override + public Object[] toObjectArray() { + return new Object[]{first, second}; + } + + @Override + public boolean equals(ArrayStore other) { + if (other instanceof FixnumImmutablePairArrayStore) { + return equals((FixnumImmutablePairArrayStore) other); + } else { + return super.equals(other); + } + } + + public boolean equals(FixnumImmutablePairArrayStore other) { + if (other == null) { + return false; + } else if (other == this) { + return true; + } else { + return other.first == first && other.second == second; + } + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/GeneraliseArrayStoreException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/GeneraliseArrayStoreException.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core.array; + +import com.oracle.truffle.api.nodes.*; + +/** + * An exception that signals that an ArrayStore cannot store a given object because of its type, and + * that the store must be generalized to accommodate it. + */ +public class GeneraliseArrayStoreException extends SlowPathException { + + private static final long serialVersionUID = -7648655548414168177L; + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/ObjectArrayStore.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/ObjectArrayStore.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core.array; + +import java.util.*; + +import com.oracle.truffle.ruby.runtime.*; + +/** + * A store for an array of any objects. + */ +public final class ObjectArrayStore extends BaseArrayStore { + + private Object[] values; + + public ObjectArrayStore() { + this(new Object[]{}); + } + + public ObjectArrayStore(Object[] values) { + this.values = values; + size = values.length; + capacity = values.length; + } + + @Override + public Object get(int normalisedIndex) { + if (normalisedIndex >= size) { + return NilPlaceholder.INSTANCE; + } + + return values[normalisedIndex]; + } + + @Override + public ArrayStore getRange(int normalisedBegin, int normalisedExclusiveEnd) { + if (normalisedBegin >= size) { + return null; // Represents Nil + } + + return new ObjectArrayStore(Arrays.copyOfRange(values, normalisedBegin, normalisedExclusiveEnd)); + } + + @Override + public void set(int normalisedIndex, Object value) throws GeneraliseArrayStoreException { + if (normalisedIndex > size) { + final int originalLength = size; + createSpace(size, normalisedIndex - size + 1); + Arrays.fill(values, originalLength, normalisedIndex, NilPlaceholder.INSTANCE); + values[normalisedIndex] = value; + } else if (normalisedIndex == size) { + push(value); + } else { + values[normalisedIndex] = value; + } + } + + @Override + public void setRangeSingle(int normalisedBegin, int normalisedExclusiveEnd, Object value) throws GeneraliseArrayStoreException { + // Is the range the whole array? + + if (normalisedBegin == 0 && normalisedExclusiveEnd == size) { + // Reset length and set the value. + size = 1; + values[0] = value; + } else { + // Delete the range, except for the first value. + deleteSpace(normalisedBegin + 1, normalisedExclusiveEnd - normalisedBegin - 1); + + // Set the value we left in. + System.err.println(normalisedBegin + " in " + size + " with " + values.length); + values[normalisedBegin] = value; + } + } + + @Override + public void setRangeArray(int normalisedBegin, int normalisedExclusiveEnd, ArrayStore other) throws GeneraliseArrayStoreException { + setRangeArray(normalisedBegin, normalisedExclusiveEnd, (ObjectArrayStore) other.generalizeFor(null)); + } + + public void setRangeArray(int normalisedBegin, int normalisedExclusiveEnd, ObjectArrayStore other) { + setRangeArrayMatchingTypes(normalisedBegin, normalisedExclusiveEnd, other.values, other.size); + } + + @Override + public void insert(int normalisedIndex, Object value) throws GeneraliseArrayStoreException { + if (normalisedIndex > size) { + final int originalLength = size; + createSpaceAtEnd(normalisedIndex - size + 1); + Arrays.fill(values, originalLength, normalisedIndex, NilPlaceholder.INSTANCE); + values[normalisedIndex] = value; + } else { + createSpace(normalisedIndex, 1); + values[normalisedIndex] = value; + } + } + + @Override + public void push(Object value) throws GeneraliseArrayStoreException { + createSpaceAtEnd(1); + values[size - 1] = value; + } + + @Override + public Object deleteAt(int normalisedIndex) { + if (normalisedIndex >= size) { + return NilPlaceholder.INSTANCE; + } + + final Object value = values[normalisedIndex]; + + deleteSpace(normalisedIndex, 1); + + return value; + } + + @Override + public ArrayStore dup() { + return new ObjectArrayStore(Arrays.copyOf(values, size)); + } + + @Override + public boolean contains(Object value) { + for (int n = 0; n < size; n++) { + if (values[n].equals(value)) { + return true; + } + } + + return false; + } + + @Override + public ObjectArrayStore generalizeFor(Object type) { + return this; + } + + @Override + public Object getIndicativeValue() { + return null; + } + + @Override + protected void setCapacityByCopying(int newCapacity) { + values = Arrays.copyOf(values, newCapacity); + capacity = values.length; + } + + @Override + protected void setCapacityWithNewArray(int newCapacity) { + values = new Object[newCapacity]; + capacity = values.length; + } + + @Override + protected Object getValuesArrayObject() { + return values; + } + + public Object[] getValues() { + return values; + } + + @Override + public Object[] toObjectArray() { + if (values.length == size) { + return values; + } else { + return Arrays.copyOf(values, size); + } + } + + @Override + public boolean equals(ArrayStore other) { + if (other instanceof ObjectArrayStore) { + return equals((ObjectArrayStore) other); + } else { + return super.equals(other); + } + } + + public boolean equals(ObjectArrayStore other) { + if (other == null) { + return false; + } else if (other == this) { + return true; + } else if (other.size != size) { + return false; + } else if (other.capacity == capacity) { + return Arrays.equals(other.values, values); + } else { + for (int n = 0; n < size; n++) { + if (!other.values[n].equals(values[n])) { + return false; + } + } + + return true; + } + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/ObjectImmutablePairArrayStore.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/ObjectImmutablePairArrayStore.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core.array; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * A store for a pair of objects. + */ +public final class ObjectImmutablePairArrayStore extends BaseArrayStore { + + private final Object first; + private final Object second; + + public ObjectImmutablePairArrayStore(Object first, Object second) { + size = 2; + capacity = 2; + this.first = first; + this.second = second; + } + + @Override + public int size() { + return 2; + } + + @Override + public Object get(int normalisedIndex) { + switch (normalisedIndex) { + case 0: + return first; + case 1: + return second; + default: + return NilPlaceholder.INSTANCE; + } + } + + @Override + public ArrayStore getRange(int normalisedBegin, int truncatedNormalisedExclusiveEnd) { + if (normalisedBegin >= size) { + return null; // Represents Nil + } + + return new ObjectArrayStore(Arrays.copyOfRange(new Object[]{first, second}, normalisedBegin, truncatedNormalisedExclusiveEnd)); + } + + @Override + public void set(int normalisedIndex, Object value) throws GeneraliseArrayStoreException { + CompilerDirectives.transferToInterpreter(); + throw new GeneraliseArrayStoreException(); + } + + @Override + public void setRangeSingle(int normalisedBegin, int truncatedNormalisedExclusiveEnd, Object value) throws GeneraliseArrayStoreException { + CompilerDirectives.transferToInterpreter(); + throw new GeneraliseArrayStoreException(); + } + + @Override + public void setRangeArray(int normalisedBegin, int normalisedExclusiveEnd, ArrayStore other) throws GeneraliseArrayStoreException { + CompilerDirectives.transferToInterpreter(); + throw new GeneraliseArrayStoreException(); + } + + @Override + public void insert(int normalisedIndex, Object value) throws GeneraliseArrayStoreException { + CompilerDirectives.transferToInterpreter(); + throw new GeneraliseArrayStoreException(); + } + + @Override + public void push(Object value) throws GeneraliseArrayStoreException { + CompilerDirectives.transferToInterpreter(); + throw new GeneraliseArrayStoreException(); + } + + @Override + public Object deleteAt(int normalisedIndex) { + throw new UnsupportedOperationException(); + } + + @Override + public ArrayStore dup() { + return this; + } + + @Override + public boolean contains(Object value) { + return first.equals(value) || second.equals(value); + } + + @Override + public ArrayStore generalizeFor(Object type) { + return new ObjectArrayStore(toObjectArray()); + } + + @Override + public Object getIndicativeValue() { + return 0; + } + + @Override + protected void setCapacityByCopying(int newCapacity) { + throw new UnsupportedOperationException(); + } + + @Override + protected void setCapacityWithNewArray(int newCapacity) { + throw new UnsupportedOperationException(); + } + + @Override + protected Object getValuesArrayObject() { + return new Object[]{first, second}; + } + + @Override + public Object[] toObjectArray() { + return new Object[]{first, second}; + } + + @Override + public boolean equals(ArrayStore other) { + if (other instanceof ObjectImmutablePairArrayStore) { + return equals((ObjectImmutablePairArrayStore) other); + } else { + return super.equals(other); + } + } + + public boolean equals(ObjectImmutablePairArrayStore other) { + if (other == null) { + return false; + } else if (other == this) { + return true; + } else { + return other.first == first && other.second == second; + } + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/RubyArray.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/array/RubyArray.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,428 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core.array; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.CompilerDirectives.SlowPath; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.methods.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Implements the Ruby {@code Array} class. + */ +@SuppressWarnings("unused") +public final class RubyArray extends RubyObject { + + public static class RubyArrayClass extends RubyClass { + + public RubyArrayClass(RubyClass objectClass) { + super(null, objectClass, "Array"); + } + + @Override + public RubyBasicObject newInstance() { + return new RubyArray(this); + } + + } + + @CompilationFinal private ArrayStore store; + + public RubyArray(RubyClass arrayClass) { + this(arrayClass, EmptyArrayStore.INSTANCE); + } + + public RubyArray(RubyClass arrayClass, ArrayStore store) { + super(arrayClass); + this.store = store; + } + + private static RubyArray selfAsArray(Object self) { + if (self instanceof RubyArray) { + return (RubyArray) self; + } else { + throw new IllegalStateException(); + } + } + + @CompilerDirectives.SlowPath + public static RubyArray specializedFromObject(RubyClass arrayClass, Object object) { + ArrayStore store; + + if (object instanceof Integer || object instanceof RubyFixnum) { + store = new FixnumArrayStore(new int[]{GeneralConversions.toFixnum(object)}); + } else { + store = new ObjectArrayStore(new Object[]{object}); + } + + return new RubyArray(arrayClass, store); + } + + /** + * Create a Ruby array from a Java array of objects, choosing the best store. + */ + @CompilerDirectives.SlowPath + public static RubyArray specializedFromObjects(RubyClass arrayClass, Object... objects) { + if (objects.length == 0) { + return new RubyArray(arrayClass); + } + + boolean canUseFixnum = true; + + for (Object object : objects) { + if (!(object instanceof Integer || object instanceof RubyFixnum)) { + canUseFixnum = false; + } + } + + ArrayStore store; + + if (canUseFixnum) { + final int[] values = new int[objects.length]; + + for (int n = 0; n < objects.length; n++) { + values[n] = GeneralConversions.toFixnum(objects[n]); + } + + store = new FixnumArrayStore(values); + } else { + store = new ObjectArrayStore(objects); + } + + return new RubyArray(arrayClass, store); + } + + public Object get(int index) { + return store.get(ArrayUtilities.normaliseIndex(store.size(), index)); + } + + public Object getRangeInclusive(int begin, int inclusiveEnd) { + final int l = store.size(); + final int normalisedInclusiveEnd = ArrayUtilities.normaliseIndex(l, inclusiveEnd); + return getRangeExclusive(begin, normalisedInclusiveEnd + 1); + } + + public Object getRangeExclusive(int begin, int exclusiveEnd) { + final int l = store.size(); + final int normalisedBegin = ArrayUtilities.normaliseIndex(l, begin); + final int truncatedNormalisedExclusiveEnd = ArrayUtilities.truncateNormalisedExclusiveIndex(l, ArrayUtilities.normaliseExclusiveIndex(l, exclusiveEnd)); + + final Object range = store.getRange(normalisedBegin, truncatedNormalisedExclusiveEnd); + + if (range == null) { + return new RubyArray(getRubyClass()); + } else { + return new RubyArray(getRubyClass(), (ArrayStore) range); + } + } + + public void set(int index, Object value) { + checkFrozen(); + + final int l = store.size(); + final int normalisedIndex = ArrayUtilities.normaliseIndex(l, index); + + try { + store.set(normalisedIndex, value); + } catch (GeneraliseArrayStoreException e) { + store = store.generalizeFor(value); + + try { + store.set(normalisedIndex, value); + } catch (GeneraliseArrayStoreException ex) { + throwSecondGeneraliseException(); + } + } + } + + public void setRangeSingleInclusive(int begin, int inclusiveEnd, Object value) { + final int l = store.size(); + final int normalisedInclusiveEnd = ArrayUtilities.normaliseIndex(l, inclusiveEnd); + setRangeSingleExclusive(begin, normalisedInclusiveEnd + 1, value); + } + + public void setRangeSingleExclusive(int begin, int exclusiveEnd, Object value) { + checkFrozen(); + + final int l = store.size(); + final int normalisedBegin = ArrayUtilities.normaliseIndex(l, begin); + final int truncatedNormalisedExclusiveEnd = ArrayUtilities.truncateNormalisedExclusiveIndex(l, ArrayUtilities.normaliseExclusiveIndex(l, exclusiveEnd)); + + try { + store.setRangeSingle(normalisedBegin, truncatedNormalisedExclusiveEnd, value); + } catch (GeneraliseArrayStoreException e) { + store = store.generalizeFor(value); + + try { + store.setRangeSingle(normalisedBegin, truncatedNormalisedExclusiveEnd, value); + } catch (GeneraliseArrayStoreException ex) { + throwSecondGeneraliseException(); + } + } + } + + public void setRangeArrayInclusive(int begin, int inclusiveEnd, RubyArray other) { + final int l = store.size(); + final int normalisedInclusiveEnd = ArrayUtilities.normaliseIndex(l, inclusiveEnd); + setRangeArrayExclusive(begin, normalisedInclusiveEnd + 1, other); + } + + public void setRangeArrayExclusive(int begin, int exclusiveEnd, RubyArray other) { + checkFrozen(); + + final int l = store.size(); + final int normalisedBegin = ArrayUtilities.normaliseIndex(l, begin); + final int normalisedExclusiveEnd = ArrayUtilities.normaliseExclusiveIndex(l, exclusiveEnd); + + try { + store.setRangeArray(normalisedBegin, normalisedExclusiveEnd, other.store); + } catch (GeneraliseArrayStoreException e) { + store = store.generalizeFor(other.store.getIndicativeValue()); + + try { + store.setRangeArray(normalisedBegin, normalisedExclusiveEnd, other.store); + } catch (GeneraliseArrayStoreException ex) { + throwSecondGeneraliseException(); + } + } + } + + public void insert(int index, Object value) { + checkFrozen(); + + final int l = store.size(); + final int normalisedIndex = ArrayUtilities.normaliseIndex(l, index); + + try { + store.insert(normalisedIndex, value); + } catch (GeneraliseArrayStoreException e) { + store = store.generalizeFor(value); + + try { + store.insert(normalisedIndex, value); + } catch (GeneraliseArrayStoreException ex) { + throwSecondGeneraliseException(); + } + } + } + + public void push(Object value) { + checkFrozen(); + + if (store instanceof EmptyArrayStore) { + /* + * Normally we want to transfer to interpreter to generalize an array store, but the + * special case of an empty array is common, will never cause rewrites and has a simple + * implementation, so treat it as a special case. + */ + store = ((EmptyArrayStore) store).generalizeFor(value); + } + + try { + store.push(value); + } catch (GeneraliseArrayStoreException e) { + store = store.generalizeFor(value); + + try { + store.push(value); + } catch (GeneraliseArrayStoreException ex) { + throw new IllegalStateException("Generalised to support a specific value, but value still rejected by store"); + } + } + } + + public void unshift(Object value) { + insert(0, value); + } + + public Object deleteAt(int index) { + checkFrozen(); + + final int l = store.size(); + final int normalisedIndex = ArrayUtilities.normaliseIndex(l, index); + + return store.deleteAt(normalisedIndex); + } + + @Override + @CompilerDirectives.SlowPath + public Object dup() { + return new RubyArray(getRubyClass(), store.dup()); + } + + public ArrayStore getArrayStore() { + return store; + } + + public List asList() { + final RubyArray array = this; + + return new AbstractList() { + + @Override + public Object get(int n) { + return array.get(n); + } + + @Override + public int size() { + return array.size(); + } + + }; + } + + public Object[] toObjectArray() { + return store.toObjectArray(); + } + + private static void throwSecondGeneraliseException() { + CompilerAsserts.neverPartOfCompilation(); + throw new RuntimeException("Generalised based on a value, but the new store also rejected that value."); + } + + public int size() { + return store.size(); + } + + public boolean contains(Object value) { + return store.contains(value); + } + + /** + * Recursive Cartesian product. + *

+ * The Array#product method is supposed to be able to take a block, to which it yields tuples as + * they are produced, so it might be worth abstracting this method into sending tuples to some + * interface, which either adds them to an array, or yields them to the block. + */ + @SlowPath + public static RubyArray product(RubyClass arrayClass, RubyArray[] arrays, int l) { + if (arrays.length - l == 1) { + final RubyArray firstArray = arrays[0]; + + final RubyArray tuples = new RubyArray(arrayClass); + + for (int i = 0; i < firstArray.size(); i++) { + final RubyArray tuple = new RubyArray(arrayClass); + tuple.push(firstArray.get(i)); + tuples.push(tuple); + } + + return tuples; + } else { + final RubyArray intermediateTuples = product(arrayClass, arrays, l - 1); + final RubyArray lastArray = arrays[l - 1]; + + final RubyArray tuples = new RubyArray(arrayClass); + + for (int n = 0; n < intermediateTuples.size(); n++) { + for (int i = 0; i < lastArray.size(); i++) { + final RubyArray tuple = (RubyArray) ((RubyArray) intermediateTuples.get(n)).dup(); + tuple.push(lastArray.get(i)); + tuples.push(tuple); + } + } + + return tuples; + } + } + + public boolean equals(RubyArray other) { + if (other == null) { + return false; + } else if (other == this) { + return true; + } else { + return store.equals(other.store); + } + } + + @Override + public boolean equals(Object other) { + if (other instanceof RubyArray) { + return equals((RubyArray) other); + } else { + return false; + } + } + + @Override + public int hashCode() { + getRubyClass().getContext().implementationMessage("Array#hash returns nonsense"); + return 0; + } + + public RubyArray relativeComplement(RubyArray other) { + // TODO(cs): specialize for different stores + + final RubyArray result = new RubyArray(getRubyClass().getContext().getCoreLibrary().getArrayClass()); + + for (Object value : asList()) { + if (!other.contains(value)) { + result.push(value); + } + } + + return result; + } + + public String join(String separator) { + final StringBuilder builder = new StringBuilder(); + + for (int n = 0; n < size(); n++) { + if (n > 0) { + builder.append(separator); + } + + builder.append(get(n).toString()); + } + + return builder.toString(); + } + + public static String join(Object[] parts, String separator) { + final StringBuilder builder = new StringBuilder(); + + for (int n = 0; n < parts.length; n++) { + if (n > 0) { + builder.append(separator); + } + + builder.append(parts[n].toString()); + } + + return builder.toString(); + } + + public void flattenTo(RubyArray result) { + for (int n = 0; n < size(); n++) { + final Object value = get(n); + + if (value instanceof RubyArray) { + ((RubyArray) value).flattenTo(result); + } else { + result.push(value); + } + } + } + + public boolean isEmpty() { + return store.size() == 0; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/range/FixnumRange.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/range/FixnumRange.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core.range; + +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +/** + * A range that has {@code Fixnum} begin and end. + */ +public class FixnumRange extends RubyRange { + + private final int begin; + private final int end; + private final boolean excludeEnd; + + public FixnumRange(RubyClass rangeClass, int begin, int end, boolean excludeEnd) { + super(rangeClass); + this.begin = begin; + this.end = end; + this.excludeEnd = excludeEnd; + } + + @Override + public String toString() { + if (excludeEnd) { + return begin + "..." + end; + } else { + return begin + ".." + end; + } + } + + @Override + public RubyArray toArray() { + final int length = getLength(); + + if (length < 0) { + return new RubyArray(getRubyClass().getContext().getCoreLibrary().getArrayClass()); + } else { + final int[] values = new int[length]; + + for (int n = 0; n < length; n++) { + values[n] = begin + n; + } + + return new RubyArray(getRubyClass().getContext().getCoreLibrary().getArrayClass(), new FixnumArrayStore(values)); + } + } + + private int getLength() { + if (excludeEnd) { + return end - begin; + } else { + return end - begin + 1; + } + } + + public final int getBegin() { + return begin; + } + + public final int getEnd() { + return end; + } + + public final int getInclusiveEnd() { + if (excludeEnd) { + return end - 1; + } else { + return end; + } + } + + public final int getExclusiveEnd() { + if (excludeEnd) { + return end; + } else { + return end + 1; + } + } + + @Override + public boolean doesExcludeEnd() { + return excludeEnd; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + begin; + result = prime * result + end; + result = prime * result + (excludeEnd ? 1231 : 1237); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof FixnumRange)) { + return false; + } + FixnumRange other = (FixnumRange) obj; + if (begin != other.begin) { + return false; + } + if (end != other.end) { + return false; + } + if (excludeEnd != other.excludeEnd) { + return false; + } + return true; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/range/ObjectRange.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/range/ObjectRange.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core.range; + +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +public class ObjectRange extends RubyRange { + + private final Object begin; + private final Object end; + private final boolean excludeEnd; + + public ObjectRange(RubyClass rangeClass, Object begin, Object end, boolean excludeEnd) { + super(rangeClass); + this.begin = begin; + this.end = end; + this.excludeEnd = excludeEnd; + } + + @Override + public RubyArray toArray() { + throw new UnsupportedOperationException(); + } + + public Object getBegin() { + return begin; + } + + public Object getEnd() { + return end; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((begin == null) ? 0 : begin.hashCode()); + result = prime * result + ((end == null) ? 0 : end.hashCode()); + result = prime * result + (excludeEnd ? 1231 : 1237); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof ObjectRange)) { + return false; + } + ObjectRange other = (ObjectRange) obj; + if (begin == null) { + if (other.begin != null) { + return false; + } + } else if (!begin.equals(other.begin)) { + return false; + } + if (end == null) { + if (other.end != null) { + return false; + } + } else if (!end.equals(other.end)) { + return false; + } + if (excludeEnd != other.excludeEnd) { + return false; + } + return true; + } + + @Override + public boolean doesExcludeEnd() { + // TODO Auto-generated method stub + return false; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/range/RubyRange.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/core/range/RubyRange.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.core.range; + +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +public abstract class RubyRange extends RubyObject { + + public RubyRange(RubyClass rangeClass) { + super(rangeClass); + } + + public abstract RubyArray toArray(); + + public abstract boolean doesExcludeEnd(); + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/MethodLocal.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/MethodLocal.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.debug; + +import com.oracle.truffle.ruby.runtime.methods.*; + +/** + * A method and local variable identifier tuple. + */ +public class MethodLocal { + + private final UniqueMethodIdentifier method; + private final String local; + + public MethodLocal(UniqueMethodIdentifier method, String local) { + super(); + this.method = method; + this.local = local; + } + + @Override + public String toString() { + return "MethodLocal [method=" + method + ", local=" + local + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((local == null) ? 0 : local.hashCode()); + result = prime * result + ((method == null) ? 0 : method.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof MethodLocal)) { + return false; + } + MethodLocal other = (MethodLocal) obj; + if (local == null) { + if (other.local != null) { + return false; + } + } else if (!local.equals(other.local)) { + return false; + } + if (method == null) { + if (other.method != null) { + return false; + } + } else if (!method.equals(other.method)) { + return false; + } + return true; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyBreakAfterProbe.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyBreakAfterProbe.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.debug; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * A Ruby probe for invoking a breakpoint shell after a child execution method completes. + */ +public final class RubyBreakAfterProbe extends RubyProbe { + + public RubyBreakAfterProbe(RubyContext context) { + super(context); + } + + @Override + public void leave(Node astNode, VirtualFrame frame) { + context.getDebugManager().haltedAt(astNode, frame.materialize()); + } + + @Override + public void leave(Node astNode, VirtualFrame frame, boolean result) { + context.getDebugManager().haltedAt(astNode, frame.materialize()); + } + + @Override + public void leave(Node astNode, VirtualFrame frame, int result) { + context.getDebugManager().haltedAt(astNode, frame.materialize()); + } + + @Override + public void leave(Node astNode, VirtualFrame frame, double result) { + context.getDebugManager().haltedAt(astNode, frame.materialize()); + } + + @Override + public void leave(Node astNode, VirtualFrame frame, Object result) { + context.getDebugManager().haltedAt(astNode, frame.materialize()); + } + + @Override + public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) { + context.getDebugManager().haltedAt(astNode, frame.materialize()); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyBreakBeforeProbe.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyBreakBeforeProbe.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.debug; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * A probe for invoking a breakpoint shell before a child execution method. + */ +public final class RubyBreakBeforeProbe extends RubyProbe { + + public RubyBreakBeforeProbe(RubyContext context) { + super(context); + } + + @Override + public void enter(Node astNode, VirtualFrame frame) { + context.getDebugManager().haltedAt(astNode, frame.materialize()); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyDebugManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyDebugManager.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.debug; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.instrument.*; +import com.oracle.truffle.api.nodes.instrument.InstrumentationProbeNode.ProbeChain; +import com.oracle.truffle.api.source.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +/** + * Manager for Ruby AST execution. + */ +public final class RubyDebugManager implements DebugManager { + + // TODO (mlvdv) no REPL support yet for debugging "locals"; only lines + + private static enum BreakpointStatus { + + /** + * Created for a source location but not yet attached for some legitimate reason: new and + * not yet attached; new and the source file hasn't been loaded yet; old and the source file + * is in the process of being reloaded. + */ + PENDING("Pending"), + + /** + * Has an active break probe in the AST. + */ + ATTACHED("Active"), + + /** + * Should be attached, but the line location cannot be found in the source. + */ + ERROR("Error: line not found"), + + /** + * Abandoned, not attached. + */ + RETIRED("Retired"); + + private final String name; + + BreakpointStatus(String name) { + this.name = name; + } + + @Override + public String toString() { + return name; + } + } + + /** + * Map: Source lines ==> source chains known to be at line locations in an AST. + */ + private final Map linesToProbeChains = new HashMap<>(); + + private final Set loadedSources = new HashSet<>(); + + private Source beingLoaded = null; + + /** + * Map: Source lines ==> attached Breakpoints/procs to be activated before execution at line. + */ + private final Map linesToBreakpoints = new TreeMap<>(); + + /** + * Map: Method locals in AST ==> Method local assignments where breakpoints can be attached. + */ + private final Map localsToProbeChains = new HashMap<>(); + + /** + * Map: Method locals ==> Breakpoints & procs to be activated after assignment to a local. + */ + private final Map localsToAttachedBreakpoints = new HashMap<>(); + + private final RubyContext context; + + public RubyDebugManager(RubyContext context) { + this.context = context; + } + + public void notifyStartLoading(Source source) { + + beingLoaded = source; + + // Forget all the probe chains from previous loading + final List locations = new ArrayList<>(); + for (SourceLineLocation lineLocation : linesToProbeChains.keySet()) { + if (lineLocation.getSource().equals(beingLoaded)) { + locations.add(lineLocation); + } + } + for (SourceLineLocation lineLocation : locations) { + linesToProbeChains.remove(lineLocation); + } + + // Forget whatever we knew, and detach from old AST/ProbeChain if needed + for (RubyLineBreakpoint breakpoint : linesToBreakpoints.values()) { + if (breakpoint.getSourceLineLocation().getSource().equals(beingLoaded)) { + breakpoint.setPending(); + } + } + } + + public void notifyFinishedLoading(Source source) { + assert source == beingLoaded; + + // Any pending breakpoints are now erroneous, didn't find the line. + for (RubyLineBreakpoint breakpoint : linesToBreakpoints.values()) { + if (breakpoint.getSourceLineLocation().getSource().equals(beingLoaded)) { + if (breakpoint.status == BreakpointStatus.PENDING) { + breakpoint.setError(); + } + } + } + + loadedSources.add(source); + beingLoaded = null; + + } + + /** + * Notifies the manager about creation of a newly created probe chain associated with a proxy + * for an AST node at a specific location in the source text. + */ + public void registerProbeChain(SourceSection sourceSection, ProbeChain probeChain) { + + assert sourceSection.getSource().equals(beingLoaded); + + // Remember this probe chain, indexed by line number + final SourceLineLocation lineLocation = new SourceLineLocation(sourceSection.getSource(), sourceSection.getStartLine()); + linesToProbeChains.put(lineLocation, probeChain); + + final RubyLineBreakpoint breakpoint = linesToBreakpoints.get(lineLocation); + if (breakpoint != null && breakpoint.location.equals(lineLocation)) { + // We only register while we're loading; + // While we're loading, there should only be pending breakpoints for this source + assert breakpoint.status == BreakpointStatus.PENDING; + + // Found a line/probeChain where a pending breakpoint should be set + breakpoint.attach(probeChain); + } + } + + @Override + public RubyLineBreakpoint setBreakpoint(SourceLineLocation lineLocation) { + + RubyLineBreakpoint breakpoint = linesToBreakpoints.get(lineLocation); + + if (breakpoint != null) { + switch (breakpoint.status) { + case ATTACHED: + throw new RuntimeException("Breakpoint already set at line " + lineLocation); + + case PENDING: + case ERROR: + throw new RuntimeException("Breakpoint already pending at line " + lineLocation); + + default: + assert false; + } + } else { + breakpoint = new RubyLineBreakpoint(lineLocation, new RubyBreakBeforeProbe(context)); + linesToBreakpoints.put(lineLocation, breakpoint); + + final ProbeChain probeChain = linesToProbeChains.get(lineLocation); + if (probeChain != null) { + breakpoint.attach(probeChain); + } + } + + return breakpoint; + } + + @Override + public RubyLineBreakpoint setConditionalBreakpoint(SourceLineLocation lineLocation, String condition) { + throw new UnsupportedOperationException("conditional breakpoints not yet supported"); + } + + @Override + public LineBreakpoint[] getBreakpoints() { + return linesToBreakpoints.values().toArray(new LineBreakpoint[0]); + } + + @Override + public void removeBreakpoint(SourceLineLocation lineLocation) { + final RubyLineBreakpoint breakpoint = linesToBreakpoints.get(lineLocation); + if (breakpoint == null) { + throw new RuntimeException("No break/proc located at line " + lineLocation); + } + linesToBreakpoints.remove(lineLocation); + breakpoint.retire(); + } + + /** + * Sets a Ruby proc of no arguments to be run before a specified line is executed. + */ + public void setLineProc(SourceLineLocation lineLocation, RubyProc proc) { + + RubyLineBreakpoint breakpoint = linesToBreakpoints.get(lineLocation); + + if (breakpoint != null) { + switch (breakpoint.status) { + case ATTACHED: + throw new RuntimeException("Breakpoint already set at line " + lineLocation); + + case PENDING: + case ERROR: + throw new RuntimeException("Breakpoint already pending at line " + lineLocation); + + default: + assert false; + } + } else { + breakpoint = new RubyLineBreakpoint(lineLocation, new RubyProcBeforeProbe(context, proc)); + linesToBreakpoints.put(lineLocation, breakpoint); + + final ProbeChain probeChain = linesToProbeChains.get(lineLocation); + if (probeChain != null) { + breakpoint.attach(probeChain); + } + } + } + + /** + * Registers the chain of probes associated with a method local variable in the AST. + */ + public void registerLocalDebugProxy(UniqueMethodIdentifier methodIdentifier, String localName, ProbeChain probeChain) { + final MethodLocal methodLocal = new MethodLocal(methodIdentifier, localName); + localsToProbeChains.put(methodLocal, probeChain); + } + + /** + * Sets a breakpoint after assignment to a method local variable in the AST. + */ + public void setLocalBreak(UniqueMethodIdentifier methodIdentifier, String localName) { + final MethodLocal methodLocal = new MethodLocal(methodIdentifier, localName); + ProbeChain probeChain = localsToProbeChains.get(methodLocal); + if (probeChain == null) { + throw new RuntimeException("Can't find method local " + methodLocal); + } + RubyProbe probe = localsToAttachedBreakpoints.get(methodLocal); + if (probe != null) { + throw new RuntimeException("Breakpoint already set on method local " + methodLocal); + } + probe = new RubyBreakAfterProbe(context); + localsToAttachedBreakpoints.put(methodLocal, probe); + probeChain.appendProbe(probe); + } + + /** + * Sets a Ruby proc of one argument to be run after a method local assignment, passed the new + * value. + */ + public void setLocalProc(UniqueMethodIdentifier methodIdentifier, String localName, RubyProc proc) { + final MethodLocal methodLocal = new MethodLocal(methodIdentifier, localName); + ProbeChain probeChain = localsToProbeChains.get(methodLocal); + if (probeChain == null) { + throw new RuntimeException("Can't find method local " + methodLocal); + } + RubyProbe probe = localsToAttachedBreakpoints.get(methodLocal); + if (probe != null) { + throw new RuntimeException("Assignment proc already set on method local " + methodLocal); + } + probe = new RubyProcAfterProbe(context, proc); + localsToAttachedBreakpoints.put(methodLocal, probe); + probeChain.appendProbe(probe); + } + + /** + * Removes a break or proc on assignment to a method local variable in the AST. + */ + public void removeLocalProbe(UniqueMethodIdentifier methodIdentifier, String localName) { + final MethodLocal methodLocal = new MethodLocal(methodIdentifier, localName); + RubyProbe probe = localsToAttachedBreakpoints.get(methodLocal); + if (probe == null) { + throw new RuntimeException("No breakpoint set on method local " + methodLocal); + } + localsToProbeChains.get(methodLocal).removeProbe(probe); + localsToAttachedBreakpoints.remove(methodLocal); + } + + /** + * Receives notification of a suspended execution context; execution resumes when this method + * returns. + * + * @param astNode a guest language AST node that represents the current execution site, assumed + * not to be any kind of {@link InstrumentationNode}, + * @param frame execution frame at the site where execution suspended + */ + public void haltedAt(Node astNode, MaterializedFrame frame) { + context.haltedAt(astNode, frame); + } + + private static final class RubyLineBreakpoint implements DebugManager.LineBreakpoint, Comparable { + + private final SourceLineLocation location; + + private RubyProbe probe; // non-null until RETIRED, but may get replaced. + private ProbeChain probeChain = null; // only non-null when ATTACHED + private BreakpointStatus status = BreakpointStatus.PENDING; + + public RubyLineBreakpoint(SourceLineLocation location, RubyProbe probe) { + this.location = location; + this.probe = probe; + } + + public SourceLineLocation getSourceLineLocation() { + return location; + } + + // ensure sorted by location + public int compareTo(Object o) { + final RubyLineBreakpoint other = (RubyLineBreakpoint) o; + return location.compareTo(other.location); + } + + @Override + public String getDebugStatus() { + return status == null ? "" : status.name; + } + + private void attach(ProbeChain chain) { + assert status == BreakpointStatus.PENDING; + + probeChain = chain; + probeChain.appendProbe(probe); + + status = BreakpointStatus.ATTACHED; + } + + private void setPending() { + switch (status) { + case ATTACHED: + detach(); + // TODO (mlvdv) replace the probe + status = BreakpointStatus.PENDING; + break; + case ERROR: + status = BreakpointStatus.PENDING; + break; + case PENDING: + break; + case RETIRED: + assert false; + break; + default: + assert false; + } + } + + public void setError() { + assert status == BreakpointStatus.PENDING; + + status = BreakpointStatus.ERROR; + } + + private void detach() { + assert status == BreakpointStatus.ATTACHED; + + probeChain.removeProbe(probe); + probeChain = null; + + status = BreakpointStatus.PENDING; + } + + private void retire() { + + if (probeChain != null) { + probeChain.removeProbe(probe); + } + probe = null; + probeChain = null; + + status = BreakpointStatus.RETIRED; + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyProbe.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyProbe.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.debug; + +import com.oracle.truffle.api.nodes.instrument.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * A "probe node" implemented specifically for the Ruby implementation; subclasses need only + * override those members of {@link InstrumentationProbeEvents} for which some action is needed. + */ +public abstract class RubyProbe extends InstrumentationProbeNode.DefaultProbeNode { + + protected final RubyContext context; + + public RubyProbe(RubyContext context) { + this.context = context; + assert context != null; + } + + public RubyContext getContext() { + return context; + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyProcAfterProbe.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyProcAfterProbe.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.debug; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * A probe for instrumenting a Ruby program with a Ruby procedure to run on the return value from + * node execution. + */ +public final class RubyProcAfterProbe extends RubyProbe { + + private final RubyProc proc; + + public RubyProcAfterProbe(RubyContext context, RubyProc proc) { + super(context); + this.proc = proc; + } + + @Override + public void leave(Node astNode, VirtualFrame frame) { + proc.call(frame.pack()); + } + + @Override + public void leave(Node astNode, VirtualFrame frame, boolean result) { + proc.call(frame.pack(), result); + } + + @Override + public void leave(Node astNode, VirtualFrame frame, int result) { + proc.call(frame.pack(), result); + } + + @Override + public void leave(Node astNode, VirtualFrame frame, double result) { + proc.call(frame.pack(), result); + } + + @Override + public void leave(Node astNode, VirtualFrame frame, Object result) { + proc.call(frame.pack(), result); + } + + @Override + public void leaveExceptional(Node astNode, VirtualFrame frame, Exception e) { + proc.call(frame.pack()); + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyProcBeforeProbe.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyProcBeforeProbe.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.debug; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * A probe for instrumenting a Ruby program with a Ruby procedure to run before a call. + */ +public final class RubyProcBeforeProbe extends RubyProbe { + + private final RubyProc proc; + + public RubyProcBeforeProbe(RubyContext context, RubyProc proc) { + super(context); + this.proc = proc; + } + + @Override + public void enter(Node astNode, VirtualFrame frame) { + proc.call(frame.pack()); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyTraceProbe.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/debug/RubyTraceProbe.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.debug; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.subsystems.*; + +/** + * A "trace" probe that has no runtime cost until activated, at which time it invokes a trace + * message. + */ +public final class RubyTraceProbe extends RubyProbe { + + private final Assumption notTracingAssumption; + + @CompilerDirectives.CompilationFinal private boolean tracingEverEnabled = false; + + public RubyTraceProbe(RubyContext context) { + super(context); + this.notTracingAssumption = context.getTraceManager().getNotTracingAssumption(); + } + + @Override + public void enter(Node astNode, VirtualFrame frame) { + if (!tracingEverEnabled) { + try { + notTracingAssumption.check(); + } catch (InvalidAssumptionException e) { + tracingEverEnabled = true; + } + } + final TraceManager traceManager = context.getTraceManager(); + if (tracingEverEnabled && traceManager.hasTraceProc()) { + final SourceSection sourceSection = astNode.getEncapsulatingSourceSection(); + traceManager.trace("line", sourceSection.getSource().getName(), sourceSection.getStartLine(), 0, null, null); + } + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/lookup/LookupFork.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/lookup/LookupFork.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.lookup; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.utilities.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +/** + * A fork in the lookup graph. Look at first and then look at second. + */ +public class LookupFork implements LookupNode { + + private LookupNode first; + private LookupNode second; + + public LookupFork(LookupNode first, LookupNode second) { + this.first = first; + this.second = second; + } + + public boolean setClassVariableIfAlreadySet(String variableName, Object value) { + if (first.setClassVariableIfAlreadySet(variableName, value)) { + return true; + } + + return second.setClassVariableIfAlreadySet(variableName, value); + } + + @Override + public Object lookupConstant(String constantName) { + final Object firstResult = first.lookupConstant(constantName); + + if (firstResult != null) { + return firstResult; + } + + return second.lookupConstant(constantName); + } + + @Override + public Object lookupClassVariable(String classVariable) { + final Object firstResult = first.lookupClassVariable(classVariable); + + if (firstResult != null) { + return firstResult; + } + + return second.lookupClassVariable(classVariable); + } + + @Override + public RubyMethod lookupMethod(String methodName) { + final RubyMethod firstResult = first.lookupMethod(methodName); + + if (firstResult != null) { + return firstResult; + } + + return second.lookupMethod(methodName); + } + + @Override + public Assumption getUnmodifiedAssumption() { + return new UnionAssumption(first.getUnmodifiedAssumption(), second.getUnmodifiedAssumption()); + } + + public LookupNode getFirst() { + return first; + } + + public LookupNode getSecond() { + return second; + } + + public Set getClassVariables() { + final Set classVariables = new HashSet<>(); + classVariables.addAll(first.getClassVariables()); + classVariables.addAll(second.getClassVariables()); + return classVariables; + } + + public void getMethods(Map methods) { + second.getMethods(methods); + first.getMethods(methods); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/lookup/LookupNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/lookup/LookupNode.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.lookup; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +/** + * A node in the lookup graph. We abstract from modules and classes because with includes and + * singletons and so on there are more nodes in the graph than there are classes and modules. + */ +public interface LookupNode { + + boolean setClassVariableIfAlreadySet(String variableName, Object value); + + Object lookupConstant(String constantName); + + Object lookupClassVariable(String variableName); + + RubyMethod lookupMethod(String methodName); + + Assumption getUnmodifiedAssumption(); + + Set getClassVariables(); + + void getMethods(Map methods); + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/lookup/LookupTerminal.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/lookup/LookupTerminal.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.lookup; + +import java.util.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.utilities.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +/** + * A terminal in the lookup graph. + */ +public class LookupTerminal implements LookupNode { + + public static final LookupTerminal INSTANCE = new LookupTerminal(); + + public boolean setClassVariableIfAlreadySet(String variableName, Object value) { + return false; + } + + @Override + public Object lookupConstant(String constantName) { + return null; + } + + @Override + public Object lookupClassVariable(String constantName) { + return null; + } + + @Override + public RubyMethod lookupMethod(String methodName) { + return null; + } + + @Override + public Assumption getUnmodifiedAssumption() { + return AlwaysValidAssumption.INSTANCE; + } + + public Set getClassVariables() { + return Collections.emptySet(); + } + + public void getMethods(Map methods) { + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/methods/Arity.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/methods/Arity.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.methods; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; + +/** + * Represents the arity, or parameter contract, of a method. + */ +public class Arity { + + private final int minimum; + public static final int NO_MINIMUM = 0; + + private final int maximum; + public static final int NO_MAXIMUM = Integer.MAX_VALUE; + + public static final Arity NO_ARGS = new Arity(0, 0); + public static final Arity ONE_ARG = new Arity(1, 1); + + public Arity(int minimum, int maximum) { + this.minimum = minimum; + this.maximum = maximum; + } + + public void checkArguments(RubyContext context, Object[] arguments) { + if (arguments.length < minimum || arguments.length > maximum) { + CompilerDirectives.transferToInterpreter(); + throw new RaiseException(context.getCoreLibrary().argumentError(arguments.length, minimum)); + } + } + + public int getMinimum() { + return minimum; + } + + public int getMaximum() { + return maximum; + } + + @Override + public String toString() { + return String.format("Arity(%d, %d)", minimum, maximum); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/methods/CallTargetMethodImplementation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/methods/CallTargetMethodImplementation.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.methods; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +public class CallTargetMethodImplementation implements MethodImplementation { + + private final CallTarget callTarget; + private final MaterializedFrame declarationFrame; + + public CallTargetMethodImplementation(CallTarget callTarget, MaterializedFrame declarationFrame) { + assert callTarget != null; + + this.callTarget = callTarget; + this.declarationFrame = declarationFrame; + } + + public Object call(PackedFrame caller, Object self, RubyProc block, Object... args) { + assert RubyContext.shouldObjectBeVisible(self); + assert RubyContext.shouldObjectsBeVisible(args); + + RubyArguments arguments = new RubyArguments(declarationFrame, self, block, args); + + final Object result = callTarget.call(caller, arguments); + + assert RubyContext.shouldObjectBeVisible(result); + + return result; + } + + public MaterializedFrame getDeclarationFrame() { + return declarationFrame; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/methods/MethodImplementation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/methods/MethodImplementation.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.methods; + +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.core.*; + +public interface MethodImplementation { + + Object call(PackedFrame caller, Object self, RubyProc block, Object... args); + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/methods/RubyMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/methods/RubyMethod.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.methods; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Any kind of Ruby method - so normal methods in classes and modules, but also blocks, procs, + * lambdas and native methods written in Java. + */ +public class RubyMethod { + + private final SourceSection sourceSection; + private final RubyModule declaringModule; + private final UniqueMethodIdentifier uniqueIdentifier; + private final String intrinsicName; + private final String name; + private final Visibility visibility; + private final boolean undefined; + + private final MethodImplementation implementation; + + public RubyMethod(SourceSection sourceSection, RubyModule declaringModule, UniqueMethodIdentifier uniqueIdentifier, String intrinsicName, String name, Visibility visibility, boolean undefined, + MethodImplementation implementation) { + this.sourceSection = sourceSection; + this.declaringModule = declaringModule; + this.uniqueIdentifier = uniqueIdentifier; + this.intrinsicName = intrinsicName; + this.name = name; + this.visibility = visibility; + this.undefined = undefined; + this.implementation = implementation; + } + + public Object call(PackedFrame caller, Object self, RubyProc block, Object... args) { + assert RubyContext.shouldObjectBeVisible(self); + assert RubyContext.shouldObjectsBeVisible(args); + + final Object result = implementation.call(caller, self, block, args); + + assert RubyContext.shouldObjectBeVisible(result); + + return result; + } + + public SourceSection getSourceSection() { + return sourceSection; + } + + public UniqueMethodIdentifier getUniqueIdentifier() { + return uniqueIdentifier; + } + + public String getIntrinsicName() { + return intrinsicName; + } + + public String getName() { + return name; + } + + public Visibility getVisibility() { + return visibility; + } + + public boolean isUndefined() { + return undefined; + } + + public MethodImplementation getImplementation() { + return implementation; + } + + public RubyMethod withNewName(String newName) { + if (newName.equals(name)) { + return this; + } + + return new RubyMethod(sourceSection, declaringModule, uniqueIdentifier, intrinsicName, newName, visibility, undefined, implementation); + } + + public RubyMethod withNewVisibility(Visibility newVisibility) { + if (newVisibility == visibility) { + return this; + } + + return new RubyMethod(sourceSection, declaringModule, uniqueIdentifier, intrinsicName, name, newVisibility, undefined, implementation); + } + + public RubyMethod withDeclaringModule(RubyModule newDeclaringModule) { + if (newDeclaringModule == declaringModule) { + return this; + } + + return new RubyMethod(sourceSection, newDeclaringModule, uniqueIdentifier, intrinsicName, name, visibility, undefined, implementation); + } + + public RubyMethod undefined() { + if (undefined) { + return this; + } + + return new RubyMethod(sourceSection, declaringModule, uniqueIdentifier, intrinsicName, name, visibility, true, implementation); + } + + public boolean isVisibleTo(RubyBasicObject caller) { + if (caller instanceof RubyModule) { + if (isVisibleTo((RubyModule) caller)) { + return true; + } + } + + if (isVisibleTo(caller.getRubyClass())) { + return true; + } + + if (isVisibleTo(caller.getSingletonClass())) { + return true; + } + + return false; + } + + private boolean isVisibleTo(RubyModule module) { + switch (visibility) { + case PUBLIC: + return true; + + case PROTECTED: + return true; + + case PRIVATE: + if (module == declaringModule) { + return true; + } + + if (module.getSingletonClass() == declaringModule) { + return true; + } + + if (module.getParentModule() != null && isVisibleTo(module.getParentModule())) { + return true; + } + + return false; + + default: + return false; + } + } + + @Override + public String toString() { + return implementation.toString(); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/methods/UniqueMethodIdentifier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/methods/UniqueMethodIdentifier.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.methods; + +/** + * An object that uniquely identifies a method as it appears in the source code, and that follows + * the method as a normal method, when it becomes a proc, when it changes access or is aliased etc. + */ +public class UniqueMethodIdentifier { + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/methods/Visibility.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/methods/Visibility.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.methods; + +/** + * Represents the visibility of a method. + */ +public enum Visibility { + PUBLIC, PROTECTED, PRIVATE +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/objects/FixnumStorageLocation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/objects/FixnumStorageLocation.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.objects; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * A storage location for Fixnums. + */ +public class FixnumStorageLocation extends PrimitiveStorageLocation { + + public FixnumStorageLocation(ObjectLayout objectLayout, long offset, int mask) { + super(objectLayout, offset, mask); + } + + @Override + public Object read(RubyBasicObject object, boolean condition) { + try { + return readFixnum(object, condition); + } catch (UnexpectedResultException e) { + return e.getResult(); + } + } + + public int readFixnum(RubyBasicObject object, boolean condition) throws UnexpectedResultException { + if (isSet(object)) { + return CompilerDirectives.unsafeGetInt(object, offset, condition, this); + } else { + throw new UnexpectedResultException(NilPlaceholder.INSTANCE); + } + } + + @Override + public void write(RubyBasicObject object, Object value) throws GeneralizeStorageLocationException { + if (value instanceof Integer) { + writeFixnum(object, (int) value); + } else if (value instanceof NilPlaceholder) { + markAsUnset(object); + } else { + throw new GeneralizeStorageLocationException(); + } + } + + public void writeFixnum(RubyBasicObject object, int value) { + CompilerDirectives.unsafePutInt(object, offset, value, null); + markAsSet(object); + } + + @Override + public Class getStoredClass() { + return Integer.class; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/objects/FloatStorageLocation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/objects/FloatStorageLocation.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.objects; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * A storage location for Floats. + */ +public class FloatStorageLocation extends PrimitiveStorageLocation { + + public FloatStorageLocation(ObjectLayout objectLayout, long offset, int mask) { + super(objectLayout, offset, mask); + } + + @Override + public Object read(RubyBasicObject object, boolean condition) { + try { + return readFloat(object, condition); + } catch (UnexpectedResultException e) { + return e.getResult(); + } + } + + public double readFloat(RubyBasicObject object, boolean condition) throws UnexpectedResultException { + if (isSet(object)) { + return CompilerDirectives.unsafeGetDouble(object, offset, condition, this); + } else { + throw new UnexpectedResultException(NilPlaceholder.INSTANCE); + } + } + + @Override + public void write(RubyBasicObject object, Object value) throws GeneralizeStorageLocationException { + if (value instanceof Double) { + writeFloat(object, (double) value); + } else if (value instanceof NilPlaceholder) { + markAsUnset(object); + } else { + throw new GeneralizeStorageLocationException(); + } + } + + public void writeFloat(RubyBasicObject object, Double value) { + CompilerDirectives.unsafePutDouble(object, offset, value, null); + markAsSet(object); + } + + @Override + public Class getStoredClass() { + return Double.class; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/objects/GeneralizeStorageLocationException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/objects/GeneralizeStorageLocationException.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.objects; + +/** + * Indicates that a storage location cannot store the type of value that you asked it to. + */ +public class GeneralizeStorageLocationException extends Exception { + + private static final long serialVersionUID = -5136358171098229961L; + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/objects/ObjectLayout.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/objects/ObjectLayout.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.objects; + +import java.lang.reflect.*; +import java.util.*; +import java.util.Map.Entry; + +import sun.misc.*; + +import com.oracle.truffle.api.nodes.*; +import com.oracle.truffle.api.nodes.NodeUtil.*; +import com.oracle.truffle.ruby.runtime.*; + +/** + * Maps names of instance variables to storage locations, which are either the offset of a primitive + * field in {@code RubyBasicObject}, or an index into an object array in {@code RubyBasicObject}. + * Object layouts are chained, with each having zero or one parents. + *

+ * Object layouts are immutable, with the methods for adding new instance variables of generalizing + * the type of existing instance variables returning new object layouts. + */ +public class ObjectLayout { + + public static final ObjectLayout EMPTY = new ObjectLayout("(empty)"); + + private final String originHint; + + private final ObjectLayout parent; + + private final Map storageLocations = new HashMap<>(); + + private final int primitiveStorageLocationsUsed; + private final int objectStorageLocationsUsed; + + public static final long FIRST_OFFSET = getFirstOffset(); + + private ObjectLayout(String originHint) { + this.originHint = originHint; + this.parent = null; + primitiveStorageLocationsUsed = 0; + objectStorageLocationsUsed = 0; + } + + public ObjectLayout(String originHint, RubyContext context, ObjectLayout parent) { + this(originHint, context, parent, new HashMap()); + } + + public ObjectLayout(String originHint, RubyContext context, ObjectLayout parent, Map storageTypes) { + this.originHint = originHint; + this.parent = parent; + + // Start our offsets from where the parent ends + + int primitiveStorageLocationIndex; + int objectStorageLocationIndex; + + if (parent == null) { + primitiveStorageLocationIndex = 0; + objectStorageLocationIndex = 0; + } else { + primitiveStorageLocationIndex = parent.primitiveStorageLocationsUsed; + objectStorageLocationIndex = parent.objectStorageLocationsUsed; + } + + // Go through the variables we've been asked to store + + for (Entry entry : storageTypes.entrySet()) { + // TODO(cs): what if parent has it, but we need a more general type? + + final String name = entry.getKey(); + final Class type = entry.getValue(); + + if (parent == null || parent.findStorageLocation(name) == null) { + boolean canStoreInPrimitive = false; + int primitivesNeeded = 0; + + if (type == Integer.class) { + canStoreInPrimitive = true; + primitivesNeeded = 1; + } else if (type == Double.class) { + canStoreInPrimitive = true; + primitivesNeeded = 2; + } + + if (canStoreInPrimitive && primitiveStorageLocationIndex + primitivesNeeded <= RubyBasicObject.PRIMITIVE_STORAGE_LOCATIONS_COUNT) { + final long offset = FIRST_OFFSET + Unsafe.ARRAY_INT_INDEX_SCALE * primitiveStorageLocationIndex; + final int mask = 1 << primitiveStorageLocationIndex; + + StorageLocation newStorageLocation = null; + + if (type == Integer.class) { + newStorageLocation = new FixnumStorageLocation(this, offset, mask); + } else if (type == Double.class) { + newStorageLocation = new FloatStorageLocation(this, offset, mask); + } + + storageLocations.put(entry.getKey(), newStorageLocation); + primitiveStorageLocationIndex += primitivesNeeded; + } else { + if (canStoreInPrimitive && context.getConfiguration().getPrintSpiltInstanceVariables()) { + context.implementationMessage("instance variable %s of type %s spilt due to lack of space", name, type.getName()); + } + + final ObjectStorageLocation newStorageLocation = new ObjectStorageLocation(this, objectStorageLocationIndex); + storageLocations.put(entry.getKey(), newStorageLocation); + objectStorageLocationIndex++; + } + } + } + + primitiveStorageLocationsUsed = primitiveStorageLocationIndex; + objectStorageLocationsUsed = objectStorageLocationIndex; + } + + /** + * Create a new version of this layout, but with a different parent. The new parent probably + * comes from the same Ruby class as it did, but it's a new layout because layouts are + * immutable, so modifications to the superclass yields a new layout. + */ + public ObjectLayout renew(RubyContext context, ObjectLayout newParent) { + return new ObjectLayout(originHint + ".renewed", context, newParent, getStorageTypes()); + } + + /** + * Create a new version of this layout but with a new variable. + */ + public ObjectLayout withNewVariable(RubyContext context, String name, Class type) { + final Map storageTypes = getStorageTypes(); + storageTypes.put(name, type); + return new ObjectLayout(originHint + ".withnew", context, parent, storageTypes); + } + + /** + * Create a new version of this layout but with an existing variable generalized to support any + * type. + */ + public ObjectLayout withGeneralisedVariable(RubyContext context, String name) { + return withNewVariable(context, name, Object.class); + } + + /** + * Get a map of instance variable names to the type that they store. + */ + public Map getStorageTypes() { + Map storageTypes = new HashMap<>(); + + for (Entry entry : storageLocations.entrySet()) { + final String name = entry.getKey(); + final StorageLocation storageLocation = entry.getValue(); + + if (storageLocation.getStoredClass() != null) { + storageTypes.put(name, storageLocation.getStoredClass()); + } + } + + return storageTypes; + } + + /** + * Get a map of instance variable names to the type that they store, but including both this + * layout and all parent layouts. + */ + public Map getAllStorageLocations() { + final Map allStorageLocations = new HashMap<>(); + + allStorageLocations.putAll(storageLocations); + + if (parent != null) { + allStorageLocations.putAll(parent.getAllStorageLocations()); + } + + return allStorageLocations; + } + + /** + * Find a storage location from a name, including in parents. + */ + public StorageLocation findStorageLocation(String name) { + final StorageLocation storageLocation = storageLocations.get(name); + + if (storageLocation != null) { + return storageLocation; + } + + if (parent == null) { + return null; + } + + return parent.findStorageLocation(name); + } + + public int getObjectStorageLocationsUsed() { + return objectStorageLocationsUsed; + } + + /** + * Does this layout include another layout? That is, is that other layout somewhere in the chain + * of parents? We say 'include' because all of the variables in a parent layout are available in + * your layout as well. + */ + public boolean contains(ObjectLayout other) { + ObjectLayout layout = this; + + do { + if (other == layout) { + return true; + } + + layout = layout.parent; + } while (layout != null); + + return false; + } + + public String getOriginHint() { + return originHint; + } + + private static long getFirstOffset() { + try { + final Field fieldOffsetProviderField = NodeUtil.class.getDeclaredField("unsafeFieldOffsetProvider"); + fieldOffsetProviderField.setAccessible(true); + final FieldOffsetProvider fieldOffsetProvider = (FieldOffsetProvider) fieldOffsetProviderField.get(null); + + final Field firstPrimitiveField = RubyBasicObject.class.getDeclaredField("primitiveStorageLocation01"); + return fieldOffsetProvider.objectFieldOffset(firstPrimitiveField); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/objects/ObjectStorageLocation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/objects/ObjectStorageLocation.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.objects; + +import com.oracle.truffle.ruby.runtime.*; + +/** + * A storage location for any object. + */ +public class ObjectStorageLocation extends StorageLocation { + + private final int index; + + public ObjectStorageLocation(ObjectLayout objectLayout, int index) { + super(objectLayout); + this.index = index; + } + + @Override + public boolean isSet(RubyBasicObject object) { + return object.objectStorageLocations[index] != null; + } + + @Override + public Object read(RubyBasicObject object, boolean condition) { + final Object result = object.objectStorageLocations[index]; + + if (result == null) { + return NilPlaceholder.INSTANCE; + } else { + return result; + } + } + + @Override + public void write(RubyBasicObject object, Object value) { + object.objectStorageLocations[index] = value; + } + + @Override + public Class getStoredClass() { + return Object.class; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/objects/PrimitiveStorageLocation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/objects/PrimitiveStorageLocation.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.objects; + +/** + * A storage location that uses one of the primitive fields in {@code RubyBasObject}. + */ +public abstract class PrimitiveStorageLocation extends StorageLocation { + + protected final long offset; + protected final int mask; + + protected PrimitiveStorageLocation(ObjectLayout objectLayout, long offset, int mask) { + super(objectLayout); + this.offset = offset; + this.mask = mask; + } + + @Override + public boolean isSet(RubyBasicObject object) { + return (object.primitiveSetMap & mask) != 0; + } + + protected void markAsSet(RubyBasicObject object) { + object.primitiveSetMap |= mask; + } + + protected void markAsUnset(RubyBasicObject object) { + object.primitiveSetMap &= ~mask; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/objects/RubyBasicObject.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/objects/RubyBasicObject.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.objects; + +import java.util.*; +import java.util.Map.Entry; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.lookup.*; +import com.oracle.truffle.ruby.runtime.methods.*; + +/** + * Represents the Ruby {@code BasicObject} class - the root of the Ruby class hierarchy. + */ +public class RubyBasicObject { + + @CompilationFinal protected RubyClass rubyClass; + protected RubyClass rubySingletonClass; + + protected LookupNode lookupNode; + + protected long objectID = -1; + + public boolean hasPrivateLayout = false; + private ObjectLayout objectLayout; + + public static final int PRIMITIVE_STORAGE_LOCATIONS_COUNT = 14; + protected int primitiveStorageLocation01; + protected int primitiveStorageLocation02; + protected int primitiveStorageLocation03; + protected int primitiveStorageLocation04; + protected int primitiveStorageLocation05; + protected int primitiveStorageLocation06; + protected int primitiveStorageLocation07; + protected int primitiveStorageLocation08; + protected int primitiveStorageLocation09; + protected int primitiveStorageLocation10; + protected int primitiveStorageLocation11; + protected int primitiveStorageLocation12; + protected int primitiveStorageLocation13; + protected int primitiveStorageLocation14; + + // A bit map to indicate which primitives are set, so that they can be Nil + protected int primitiveSetMap; + + protected Object[] objectStorageLocations; + + public RubyBasicObject(RubyClass rubyClass) { + if (rubyClass != null) { + unsafeSetRubyClass(rubyClass); + + if (rubyClass.getContext().getConfiguration().getFullObjectSpace()) { + rubyClass.getContext().getObjectSpaceManager().add(this); + } + } + } + + public void initialize() { + } + + public LookupNode getLookupNode() { + return lookupNode; + } + + public RubyClass getRubyClass() { + assert rubyClass != null; + return rubyClass; + } + + public boolean hasPrivateLayout() { + return hasPrivateLayout; + } + + public ObjectLayout getObjectLayout() { + return objectLayout; + } + + public ObjectLayout getUpdatedObjectLayout() { + updateLayout(); + return objectLayout; + } + + /** + * Does this object have an instance variable defined? + */ + public boolean isInstanceVariableDefined(String name) { + if (!hasPrivateLayout && objectLayout != rubyClass.getObjectLayoutForInstances()) { + updateLayout(); + } + + return objectLayout.findStorageLocation(name) != null; + } + + /** + * Set an instance variable to be a value. Slow path. + */ + public void setInstanceVariable(String name, Object value) { + CompilerAsserts.neverPartOfCompilation(); + + // If the object's layout doesn't match the class, update + + if (!hasPrivateLayout && objectLayout != rubyClass.getObjectLayoutForInstances()) { + updateLayout(); + } + + // Find the storage location + + StorageLocation storageLocation = objectLayout.findStorageLocation(name); + + if (storageLocation == null) { + /* + * It doesn't exist, so create a new layout for the class that includes it and update + * the layout of this object. + */ + + rubyClass.setObjectLayoutForInstances(rubyClass.getObjectLayoutForInstances().withNewVariable(rubyClass.getContext(), name, value.getClass())); + updateLayout(); + + storageLocation = objectLayout.findStorageLocation(name); + } + + // Try to write to that storage location + + try { + storageLocation.write(this, value); + } catch (GeneralizeStorageLocationException e) { + /* + * It might not be able to store the type that we passed, if not generalize the class's + * layout and update the layout of this object. + */ + + rubyClass.setObjectLayoutForInstances(rubyClass.getObjectLayoutForInstances().withGeneralisedVariable(rubyClass.getContext(), name)); + updateLayout(); + + storageLocation = objectLayout.findStorageLocation(name); + + // Try to write to the generalized storage location + + try { + storageLocation.write(this, value); + } catch (GeneralizeStorageLocationException e1) { + // We know that we just generalized it, so this should not happen + throw new RuntimeException("Generalised an instance variable, but it still rejected the value"); + } + } + } + + /** + * Get the value of an instance variable, or Nil if it isn't defined. Slow path. + */ + public Object getInstanceVariable(String name) { + CompilerAsserts.neverPartOfCompilation(); + + // If the object's layout doesn't match the class, update + + if (!hasPrivateLayout && objectLayout != rubyClass.getObjectLayoutForInstances()) { + updateLayout(); + } + + // Find the storage location + + final StorageLocation storageLocation = objectLayout.findStorageLocation(name); + + // Get the value + + if (storageLocation == null) { + return NilPlaceholder.INSTANCE; + } + + return storageLocation.read(this, true); + } + + public String[] getInstanceVariableNames() { + final Set instanceVariableNames = getInstanceVariables().keySet(); + return instanceVariableNames.toArray(new String[instanceVariableNames.size()]); + } + + public RubyClass getSingletonClass() { + if (rubySingletonClass == null) { + /* + * The object a of class A has a singleton class a' of class Class, with name + * #>, and with superclass that is A. + * + * irb(main):001:0> class A; end + * + * => nil + * + * irb(main):002:0> a = A.new + * + * => # + * + * irb(main):003:0> a.singleton_class + * + * => #> + * + * irb(main):004:0> a.singleton_class.class + * + * => Class + * + * irb(main):005:0> a.singleton_class.superclass + * + * => A + */ + + rubySingletonClass = new RubyClass(rubyClass.getParentModule(), rubyClass, String.format("#>", rubyClass.getName(), getObjectID()), true); + + lookupNode = new LookupFork(rubySingletonClass, rubyClass); + } + + return rubySingletonClass; + } + + public long getObjectID() { + if (objectID == -1) { + objectID = rubyClass.getContext().getNextObjectID(); + } + + return objectID; + } + + public String inspect() { + return toString(); + } + + /** + * Get a map of all instance variables. + */ + protected Map getInstanceVariables() { + if (objectLayout == null) { + return Collections.emptyMap(); + } + + final Map instanceVariableMap = new HashMap<>(); + + for (Entry entry : objectLayout.getAllStorageLocations().entrySet()) { + final String name = entry.getKey(); + final StorageLocation storageLocation = entry.getValue(); + + if (storageLocation.isSet(this)) { + instanceVariableMap.put(name, storageLocation.read(this, true)); + } + } + + return instanceVariableMap; + } + + /** + * Set instance variables from a map. + */ + protected void setInstanceVariables(Map instanceVariables) { + assert instanceVariables != null; + + if (objectLayout == null) { + updateLayout(); + } + + for (Entry entry : instanceVariables.entrySet()) { + final StorageLocation storageLocation = objectLayout.findStorageLocation(entry.getKey()); + assert storageLocation != null; + + try { + storageLocation.write(this, entry.getValue()); + } catch (GeneralizeStorageLocationException e) { + throw new RuntimeException("Should not have to be generalising when setting instance variables - " + entry.getValue().getClass().getName() + ", " + + storageLocation.getStoredClass().getName()); + } + } + } + + /** + * Update the layout of this object to match that of its class. + */ + @CompilerDirectives.SlowPath + public void updateLayout() { + // Get the current values of instance variables + + final Map instanceVariableMap = getInstanceVariables(); + + // Use the layout of the class + + objectLayout = rubyClass.getObjectLayoutForInstances(); + + // Make all primitives as unset + + primitiveSetMap = 0; + + // Create a new array for objects + + allocateObjectStorageLocations(); + + // Restore values + + setInstanceVariables(instanceVariableMap); + } + + private void allocateObjectStorageLocations() { + final int objectStorageLocationsUsed = objectLayout.getObjectStorageLocationsUsed(); + + if (objectStorageLocationsUsed == 0) { + objectStorageLocations = null; + } else { + objectStorageLocations = new Object[objectStorageLocationsUsed]; + } + } + + public void switchToPrivateLayout() { + final RubyContext context = getRubyClass().getContext(); + + final Map instanceVariables = getInstanceVariables(); + + hasPrivateLayout = true; + objectLayout = ObjectLayout.EMPTY; + + for (Entry entry : instanceVariables.entrySet()) { + objectLayout = objectLayout.withNewVariable(context, entry.getKey(), entry.getValue().getClass()); + } + + setInstanceVariables(instanceVariables); + } + + public void extend(RubyModule module) { + getSingletonClass().include(module); + } + + @Override + public String toString() { + return "#<" + rubyClass.getName() + ":0x" + Long.toHexString(getObjectID()) + ">"; + } + + public boolean hasSingletonClass() { + return rubySingletonClass != null; + } + + public Object send(String name, RubyProc block, Object... args) { + final RubyMethod method = getLookupNode().lookupMethod(name); + + if (method == null || method.isUndefined()) { + throw new RaiseException(getRubyClass().getContext().getCoreLibrary().noMethodError(name, toString())); + } + + return method.call(null, this, block, args); + } + + public void unsafeSetRubyClass(RubyClass newRubyClass) { + assert rubyClass == null; + + rubyClass = newRubyClass; + lookupNode = rubyClass; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/objects/StorageLocation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/objects/StorageLocation.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.objects; + +/** + * A storage location that abstracts the method for reading and writing values. + */ +public abstract class StorageLocation { + + private ObjectLayout objectLayout; + + protected StorageLocation(ObjectLayout objectLayout) { + this.objectLayout = objectLayout; + } + + public abstract boolean isSet(RubyBasicObject object); + + public abstract Object read(RubyBasicObject object, boolean condition); + + public abstract void write(RubyBasicObject object, Object value) throws GeneralizeStorageLocationException; + + public abstract Class getStoredClass(); + + public ObjectLayout getObjectLayout() { + return objectLayout; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/objects/Unboxable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/objects/Unboxable.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.objects; + +/** + * An object that can be losslessly unboxed back to a more primitive value. + */ +public interface Unboxable { + + Object unbox(); + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/subsystems/AtExitManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/subsystems/AtExitManager.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.subsystems; + +import java.util.*; + +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * Manages at_exit callbacks. + */ +public class AtExitManager { + + private final List blocks = new ArrayList<>(); + + public void add(RubyProc block) { + blocks.add(block); + } + + public void run() { + final ListIterator iterator = blocks.listIterator(blocks.size()); + + while (iterator.hasPrevious()) { + iterator.previous().call(null); + } + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/subsystems/FeatureManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/subsystems/FeatureManager.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.subsystems; + +import java.io.*; +import java.net.*; +import java.util.*; + +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.control.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +/** + * Manages the features loaded into Ruby. This basically means which library files are loaded, but + * Ruby often talks about requiring features, not files. + * + */ +public class FeatureManager { + + private RubyContext context; + + private final Set requiredFiles = new HashSet<>(); + + public FeatureManager(RubyContext context) { + this.context = context; + } + + public boolean require(String feature) throws IOException { + // Some features are handled specially + + if (context.getConfiguration().getRubyVersion().is19OrLater() && feature.equals("continuation")) { + // We always load continuations + return true; + } + + if (feature.equals("stringio")) { + context.implementationMessage("stringio not yet implemented"); + return true; + } + + if (feature.equals("rbconfig")) { + // Kernel#rbconfig is always there + return true; + } + + if (feature.equals("pp")) { + // Kernel#pretty_inspect is always there + return true; + } + + // Get the load path + + final Object loadPathObject = context.getCoreLibrary().getGlobalVariablesObject().getInstanceVariable("$:"); + + if (!(loadPathObject instanceof RubyArray)) { + throw new RuntimeException("$: is not an array"); + } + + final List loadPath = ((RubyArray) loadPathObject).asList(); + + // Try as a full path + + if (requireInPath("", feature)) { + return true; + } + + // Try each load path in turn + + for (Object pathObject : loadPath) { + final String path = pathObject.toString(); + + if (requireInPath(path, feature)) { + return true; + } + } + + // Didn't find the feature + + throw new RaiseException(context.getCoreLibrary().loadErrorCannotLoad(feature)); + } + + public boolean requireInPath(String path, String feature) throws IOException { + if (requireFile(feature)) { + return true; + } + + if (requireFile(feature + ".rb")) { + return true; + } + + if (requireFile(path + File.separator + feature)) { + return true; + } + + if (requireFile(path + File.separator + feature + ".rb")) { + return true; + } + + return false; + } + + private boolean requireFile(String fileName) throws IOException { + if (requiredFiles.contains(fileName)) { + return true; + } + + /* + * There is unfortunately no way to check if a string is a file path, or a URL. file:foo.txt + * is a valid file name, as well as a valid URL. We try as a file path first. + */ + + if (new File(fileName).isFile()) { + context.loadFile(fileName); + requiredFiles.add(fileName); + return true; + } else { + URL url; + + try { + url = new URL(fileName); + } catch (MalformedURLException e) { + return false; + } + + InputStream inputStream; + + try { + inputStream = url.openConnection().getInputStream(); + } catch (IOException e) { + return false; + } + + context.load(context.getSourceManager().get(url.toString(), inputStream)); + requiredFiles.add(fileName); + return true; + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/subsystems/FiberManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/subsystems/FiberManager.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.subsystems; + +import java.util.*; +import java.util.concurrent.*; + +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * Manages Ruby {@code Fiber} objects. + */ +public class FiberManager { + + private final RubyFiber rootFiber; + private RubyFiber currentFiber; + + private final Set runningFibers = Collections.newSetFromMap(new ConcurrentHashMap()); + + public FiberManager(RubyContext context) { + rootFiber = new RubyFiber(context.getCoreLibrary().getFiberClass(), this, context.getThreadManager()); + currentFiber = rootFiber; + } + + public RubyFiber getCurrentFiber() { + return currentFiber; + } + + public void setCurrentFiber(RubyFiber fiber) { + currentFiber = fiber; + } + + public void registerFiber(RubyFiber fiber) { + runningFibers.add(fiber); + } + + public void unregisterFiber(RubyFiber fiber) { + runningFibers.remove(fiber); + } + + public void shutdown() { + for (RubyFiber fiber : runningFibers) { + fiber.shutdown(); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/subsystems/ObjectSpaceManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/subsystems/ObjectSpaceManager.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.subsystems; + +import java.lang.ref.*; +import java.util.*; +import java.util.concurrent.*; + +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +/** + * Supports the Ruby {@code ObjectSpace} module. Object IDs are lazily allocated {@code long} + * values, mapped to objects with a weak hash map. Finalizers are implemented with weak references + * and reference queues, and are run in a dedicated Ruby thread (but not a dedicated Java thread). + */ +public class ObjectSpaceManager { + + private class FinalizerReference extends WeakReference { + + public List finalizers = new LinkedList<>(); + + public FinalizerReference(RubyBasicObject object, ReferenceQueue queue) { + super(object, queue); + } + + public void addFinalizer(RubyProc proc) { + finalizers.add(proc); + } + + public List getFinalizers() { + return finalizers; + } + + public void clearFinalizers() { + finalizers = new LinkedList<>(); + } + + } + + private final RubyContext context; + + // TODO(cs): this is wrong - WeakHashMap is not weak in the value + private final WeakHashMap objects = new WeakHashMap<>(); + + private final Map finalizerReferences = new WeakHashMap<>(); + private final ReferenceQueue finalizerQueue = new ReferenceQueue<>(); + private RubyThread finalizerThread; + private Thread finalizerJavaThread; + private boolean stop; + private CountDownLatch finished = new CountDownLatch(1); + + public ObjectSpaceManager(RubyContext context) { + this.context = context; + } + + public void add(RubyBasicObject object) { + objects.put(object.getObjectID(), object); + } + + public RubyBasicObject lookupId(long id) { + return objects.get(id); + } + + public void defineFinalizer(RubyBasicObject object, RubyProc proc) { + // Record the finalizer against the object + + FinalizerReference finalizerReference = finalizerReferences.get(object); + + if (finalizerReference == null) { + finalizerReference = new FinalizerReference(object, finalizerQueue); + finalizerReferences.put(object, finalizerReference); + } + + finalizerReference.addFinalizer(proc); + + // If there is no finalizer thread, start one + + if (finalizerThread == null) { + finalizerThread = new RubyThread(context.getCoreLibrary().getThreadClass(), context.getThreadManager()); + + finalizerThread.initialize(new Runnable() { + + @Override + public void run() { + runFinalizers(); + } + + }); + } + } + + public void undefineFinalizer(RubyBasicObject object) { + final FinalizerReference finalizerReference = finalizerReferences.get(object); + + if (finalizerReference != null) { + finalizerReference.clearFinalizers(); + } + } + + private void runFinalizers() { + // Run in a loop + + while (true) { + // Is there a finalizer ready to immediately run? + + FinalizerReference finalizerReference = (FinalizerReference) finalizerQueue.poll(); + + if (finalizerReference != null) { + runFinalizers(finalizerReference); + continue; + } + + // Check if we've been asked to stop + + if (stop) { + break; + } + + // Leave the global lock and wait on the finalizer queue + + final RubyThread runningThread = context.getThreadManager().leaveGlobalLock(); + finalizerJavaThread = Thread.currentThread(); + + try { + finalizerReference = (FinalizerReference) finalizerQueue.remove(); + } catch (InterruptedException e) { + continue; + } finally { + context.getThreadManager().enterGlobalLock(runningThread); + } + + runFinalizers(finalizerReference); + } + + finished.countDown(); + } + + private static void runFinalizers(FinalizerReference finalizerReference) { + try { + for (RubyProc proc : finalizerReference.getFinalizers()) { + proc.call(null); + } + } catch (Exception e) { + // MRI seems to silently ignore exceptions in finalizers + } + } + + public void shutdown() { + context.getThreadManager().enterGlobalLock(finalizerThread); + + try { + // Tell the finalizer thread to stop and wait for it to do so + + if (finalizerThread != null) { + stop = true; + + if (finalizerJavaThread != null) { + finalizerJavaThread.interrupt(); + } + + context.getThreadManager().leaveGlobalLock(); + + try { + finished.await(); + } catch (InterruptedException e) { + } finally { + context.getThreadManager().enterGlobalLock(finalizerThread); + } + } + + // Run any finalizers for objects that are still live + + for (FinalizerReference finalizerReference : finalizerReferences.values()) { + runFinalizers(finalizerReference); + } + } finally { + context.getThreadManager().leaveGlobalLock(); + } + } + + public Collection getObjects() { + return objects.values(); + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/subsystems/ThreadManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/subsystems/ThreadManager.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.subsystems; + +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.locks.*; + +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * Manages Ruby {@code Thread} objects. + */ +public class ThreadManager { + + private final ReentrantLock globalLock = new ReentrantLock(); + + private final RubyThread rootThread; + private RubyThread currentThread; + + private final Set runningThreads = Collections.newSetFromMap(new ConcurrentHashMap()); + + public ThreadManager(RubyContext context) { + rootThread = new RubyThread(context.getCoreLibrary().getFiberClass(), this); + runningThreads.add(rootThread); + enterGlobalLock(rootThread); + } + + /** + * Enters the global lock. Reentrant, but be aware that Ruby threads are not one-to-one with + * Java threads. Needs to be told which Ruby thread is becoming active as it can't work this out + * from the current Java thread. Remember to call {@link #leaveGlobalLock} again before + * blocking. + */ + public void enterGlobalLock(RubyThread thread) { + globalLock.lock(); + currentThread = thread; + } + + /** + * Leaves the global lock, returning the Ruby thread which has just stopped being the current + * thread. Remember to call {@link #enterGlobalLock} again with that returned thread before + * executing any Ruby code. You probably want to use this with a {@code finally} statement to + * make sure that happens + */ + public RubyThread leaveGlobalLock() { + if (!globalLock.isHeldByCurrentThread()) { + throw new RuntimeException("You don't own this lock!"); + } + + final RubyThread result = currentThread; + globalLock.unlock(); + return result; + } + + public RubyThread getCurrentThread() { + return currentThread; + } + + public void registerThread(RubyThread thread) { + runningThreads.add(thread); + } + + public void unregisterThread(RubyThread thread) { + runningThreads.remove(thread); + } + + public void shutdown() { + for (RubyThread thread : runningThreads) { + thread.shutdown(); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/subsystems/TraceManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/subsystems/TraceManager.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.runtime.subsystems; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.utilities.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; + +/** + * Manages trace events and calls the user's trace method if one is set. + *

+ * Once tracing has been enabled via {@link #setTraceProc(RubyProc)}, the underlying instrumentation + * remains in effect, along with performance impact. + */ +public final class TraceManager { + + private RubyContext context; + + private final AssumedValue traceProc = new AssumedValue<>("trace-proc", null); + private boolean suspended; + + private String lastFile; + private int lastLine; + + private final Assumption notTracingAssumption = Truffle.getRuntime().createAssumption("tracing-disabled"); + + public TraceManager(RubyContext context) { + this.context = context; + } + + /** + * Produce a trace; it is a runtime error if {@link #hasTraceProc()}{@code == false}. + */ + @CompilerDirectives.SlowPath + public void trace(String event, String file, int line, long objectId, RubyBinding binding, String className) { + // If tracing is suspended, stop here + + if (suspended) { + return; + } + + // If the file and line haven't changed since the last trace, stop here + + if (file.equals(lastFile) && line == lastLine) { + return; + } + + final RubyClass stringClass = context.getCoreLibrary().getStringClass(); + + // Suspend tracing while we run the trace proc + + suspended = true; + + try { + // Exceptions from within the proc propagate normally + + traceProc.get().call(null, new RubyString(stringClass, event), // + new RubyString(stringClass, file), // + line, // + GeneralConversions.fixnumOrBignum(objectId), // + GeneralConversions.instanceOrNil(binding), // + GeneralConversions.instanceOrNil(className)); + } finally { + // Resume tracing + + suspended = false; + } + + // Remember the last trace event file and line + + lastFile = file; + lastLine = line; + } + + /** + * Is there a "trace proc" in effect? + */ + public boolean hasTraceProc() { + return traceProc.get() != null; + } + + /** + * Gets the assumption that there has never yet been tracing enabled. Once the assumption is + * invalidated, tracing is presumed permanently enabled even if {@link #hasTraceProc()} returns + * {@code false}. + */ + public Assumption getNotTracingAssumption() { + return notTracingAssumption; + } + + public void setTraceProc(RubyProc newTraceProc) { + if (!context.getConfiguration().getTrace()) { + throw new RuntimeException("You need the --trace option to use tracing"); + } + + traceProc.set(newTraceProc); + lastFile = null; + lastLine = -1; + + notTracingAssumption.invalidate(); + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.shell/src/com/oracle/truffle/ruby/shell/CommandLineOptions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.shell/src/com/oracle/truffle/ruby/shell/CommandLineOptions.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.shell; + +import java.util.*; + +import com.oracle.truffle.ruby.runtime.configuration.*; + +/** + * Options resulting from parsing a command line by {@link CommandLineParser}. + */ +public class CommandLineOptions { + + private final List preRequires; + private final String preChangeDirectory; + + private final List extraLoadPath; + + private final String programFile; + private final List commandLineScripts; + private final List programArgs; + private final List switchArgs; + + private final int recordSeparator; + private final boolean autosplit; + private final String autosplitPattern; + private final boolean checkSyntaxOnly; + private final boolean lineEndingProcessing; + private final boolean inPlaceEdit; + private final String inPlaceBackupExtension; + private final boolean implicitLoop; + private final boolean implicitSedLoop; + private final boolean importFromPath; + private final boolean stripMessage; + private final boolean useJLine; + + private final Configuration configuration; + + public CommandLineOptions(List preRequires, String preChangeDirectory, List extraLoadPath, String programFile, List commandLineScripts, List programArgs, + List switchArgs, int recordSeparator, boolean autosplit, String autosplitPattern, boolean checkSyntaxOnly, boolean lineEndingProcessing, boolean inPlaceEdit, + String inPlaceBackupExtension, boolean implicitLoop, boolean implicitSedLoop, boolean importFromPath, boolean stripMessage, boolean useJLine, Configuration configuration) { + this.preRequires = preRequires; + this.preChangeDirectory = preChangeDirectory; + this.extraLoadPath = extraLoadPath; + this.programFile = programFile; + this.commandLineScripts = commandLineScripts; + this.programArgs = programArgs; + this.switchArgs = switchArgs; + this.recordSeparator = recordSeparator; + this.autosplit = autosplit; + this.autosplitPattern = autosplitPattern; + this.checkSyntaxOnly = checkSyntaxOnly; + this.lineEndingProcessing = lineEndingProcessing; + this.inPlaceEdit = inPlaceEdit; + this.inPlaceBackupExtension = inPlaceBackupExtension; + this.implicitLoop = implicitLoop; + this.implicitSedLoop = implicitSedLoop; + this.importFromPath = importFromPath; + this.stripMessage = stripMessage; + this.useJLine = useJLine; + this.configuration = configuration; + } + + public List getPreRequires() { + return preRequires; + } + + public String getPreChangeDirectory() { + return preChangeDirectory; + } + + public List getExtraLoadPath() { + return extraLoadPath; + } + + public String getProgramFile() { + return programFile; + } + + public List getCommandLineScripts() { + return commandLineScripts; + } + + public List getProgramArgs() { + return programArgs; + } + + public List getSwitchArgs() { + return switchArgs; + } + + public int getRecordSeparator() { + return recordSeparator; + } + + public String getAutosplitPattern() { + return autosplitPattern; + } + + public boolean isAutosplit() { + return autosplit; + } + + public boolean isCheckSyntaxOnly() { + return checkSyntaxOnly; + } + + public boolean isLineEndingProcessing() { + return lineEndingProcessing; + } + + public boolean isInPlaceEdit() { + return inPlaceEdit; + } + + public String getInPlaceBackupExtension() { + return inPlaceBackupExtension; + } + + public boolean isImplicitLoop() { + return implicitLoop; + } + + public boolean isImplicitSedLoop() { + return implicitSedLoop; + } + + public boolean isImportFromPath() { + return importFromPath; + } + + public boolean isStripMessage() { + return stripMessage; + } + + public boolean useJLine() { + return useJLine; + } + + public Configuration getConfiguration() { + return configuration; + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.shell/src/com/oracle/truffle/ruby/shell/CommandLineParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.shell/src/com/oracle/truffle/ruby/shell/CommandLineParser.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.shell; + +import java.io.*; +import java.util.*; + +import com.oracle.truffle.ruby.runtime.configuration.*; + +/** + * MRI-compatible command line parser, producing {@link CommandLineOptions}. + */ +public abstract class CommandLineParser { + + /** + * Parse an MRI-compatible command line. + */ + public static CommandLineOptions parse(String[] args) { + assert args != null; + + final List preRequires = new ArrayList<>(); + String preChangeDirectory = null; + + final List extraLoadPath = new ArrayList<>(); + + String programFile = null; + final List commandLineScripts = new ArrayList<>(); + final List programArgs = new ArrayList<>(); + final List switchArgs = new ArrayList<>(); + + int recordSeparator = -1; + boolean autosplit = false; + String autosplitPattern = null; + boolean checkSyntaxOnly = false; + boolean lineEndingProcessing = false; + boolean inPlaceEdit = false; + String inPlaceBackupExtension = null; + boolean implicitLoop = false; + boolean implicitSedLoop = false; + boolean importFromPath = false; + boolean messageStrip = false; + boolean useJLine = true; + + final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); + + final List normalizedArgs = normalizeArgs(args); + + boolean stillRubyArgs = true; + boolean collectingSwitchArgs = false; + int n = 0; + + while (n < normalizedArgs.size()) { + final String arg = normalizedArgs.get(n); + + if (stillRubyArgs && arg.startsWith("-")) { + if (collectingSwitchArgs) { + switchArgs.add(arg); + } else if (arg.startsWith("-0")) { + if (arg.length() == 2) { + recordSeparator = 0; + } else { + recordSeparator = Integer.parseInt(arg.substring(2), 8); + } + } else if (arg.startsWith("-i")) { + inPlaceEdit = true; + + if (arg.length() > 2) { + inPlaceBackupExtension = arg.substring(2); + } + } else if (arg.startsWith("-W")) { + if (arg.length() == 2) { + configurationBuilder.setWarningLevel(2); + } else if (arg.startsWith("-Wlevel=")) { + configurationBuilder.setWarningLevel(Integer.parseInt(arg.substring("-Wlevel=".length()))); + } else { + throw new IllegalArgumentException("bad flag " + arg); + } + } else if (arg.startsWith("-T")) { + if (arg.length() == 2) { + configurationBuilder.setTaintCheckLevel(1); + } else if (arg.startsWith("-Tlevel=")) { + configurationBuilder.setTaintCheckLevel(Integer.parseInt(arg.substring("-Tlevel=".length()))); + } else { + throw new IllegalArgumentException("bad flag " + arg); + } + } else if (arg.startsWith("-x")) { + messageStrip = true; + + if (arg.length() > 2) { + preChangeDirectory = arg.substring(2); + } + } else { + switch (arg) { + case "-C": + case "-e": + case "-E": + case "-F": + case "-I": + case "-r": + case "--home": + if (n + 1 >= normalizedArgs.size()) { + throw new RuntimeException("Expecting value after " + arg); + } + } + + switch (arg) { + case "--": + stillRubyArgs = false; + break; + case "-a": + autosplit = true; + break; + case "-c": + checkSyntaxOnly = true; + break; + case "-C": + if (n + 1 >= normalizedArgs.size()) { + throw new RuntimeException("Need a directory path after -C"); + } + preChangeDirectory = normalizedArgs.get(n + 1); + n++; + break; + case "-d": + case "--debug": + configurationBuilder.setDebug(true); + break; + case "--no-debug": + configurationBuilder.setDebug(false); + break; + case "--trace": + configurationBuilder.setTrace(true); + break; + case "--no-trace": + configurationBuilder.setTrace(false); + break; + case "-e": + commandLineScripts.add(normalizedArgs.get(n + 1)); + n++; + break; + case "-E": + final String[] encodings = normalizedArgs.get(n + 1).split(":"); + configurationBuilder.setDefaultExternalEncoding(encodings[0]); + + if (encodings.length == 2) { + configurationBuilder.setDefaultInternalEncoding(encodings[1]); + } else { + throw new IllegalArgumentException("bad flag " + arg); + } + + n++; + break; + case "-F": + autosplitPattern = normalizedArgs.get(n + 1); + n++; + break; + case "-I": + extraLoadPath.add(normalizedArgs.get(n + 1)); + n++; + break; + case "-l": + lineEndingProcessing = true; + break; + case "-n": + implicitLoop = true; + break; + case "-r": + preRequires.add(normalizedArgs.get(n + 1)); + n++; + break; + case "-s": + collectingSwitchArgs = true; + break; + case "-p": + implicitSedLoop = true; + break; + case "-S": + importFromPath = true; + break; + case "-w": + configurationBuilder.setWarningLevel(1); + break; + case "-h": + case "--help": + help(System.out); + return null; + case "-v": + version(System.out); + configurationBuilder.setVerbose(true); + break; + case "--version": + version(System.out); + return null; + case "--copyright": + copyright(System.out); + return null; + case "--home": + configurationBuilder.setStandardLibrary(normalizedArgs.get(n + 1) + "/" + ConfigurationBuilder.JRUBY_STDLIB_JAR); + n++; + break; + case "--stdlib": + configurationBuilder.setStandardLibrary(normalizedArgs.get(n + 1)); + n++; + break; + case "--1.8": + configurationBuilder.setRubyVersion(RubyVersion.RUBY_18); + break; + case "--1.9": + configurationBuilder.setRubyVersion(RubyVersion.RUBY_19); + break; + case "--2.0": + configurationBuilder.setRubyVersion(RubyVersion.RUBY_20); + break; + case "--full-object-space": + configurationBuilder.setFullObjectSpace(true); + break; + case "--no-jline": + useJLine = false; + break; + case "--print-parse-tree": + configurationBuilder.setPrintParseTree(true); + break; + case "--print-executed-files": + configurationBuilder.setPrintExecutedFiles(true); + break; + case "--print-spilt-instance-variables": + configurationBuilder.setPrintSpiltInstanceVariables(true); + break; + case "--print-uninitialized-calls": + configurationBuilder.setPrintUninitializedCalls(true); + break; + case "--print-java-exceptions": + configurationBuilder.setPrintJavaExceptions(true); + break; + case "--print-ruby-exceptions": + configurationBuilder.setPrintRubyExceptions(true); + break; + default: + throw new IllegalArgumentException("unknown flag " + arg); + } + } + } else if (programFile == null) { + programFile = arg; + stillRubyArgs = false; + } else { + programArgs.add(arg); + } + + n++; + } + + return new CommandLineOptions(preRequires, preChangeDirectory, extraLoadPath, programFile, commandLineScripts, programArgs, switchArgs, recordSeparator, autosplit, autosplitPattern, + checkSyntaxOnly, lineEndingProcessing, inPlaceEdit, inPlaceBackupExtension, implicitLoop, implicitSedLoop, importFromPath, messageStrip, useJLine, new Configuration( + configurationBuilder)); + } + + /** + * Produce a canonical set of arguments that includes {@code $RUBYOPT} and has contractions such + * as a {@code -rdir} replaced with separate arguments {@code -r} and {@code dir} for simpler + * processing. + */ + private static List normalizeArgs(String[] args) { + assert args != null; + + // Arguments come from the main method arguments parameter and $RUBYOPT + + final List inputArgs = new ArrayList<>(); + + final String rubyoptVar = System.getenv("RUBYOPT"); + + if (rubyoptVar != null) { + /* + * TODO(cs): what we've got here is a string that we are supposed to treat as if it was + * an extra part of the command line, including more Ruby options. However, we just get + * the string and have to split it into arguments ourselves. Normally the shell does + * that, including lots of fancy quoting styles. Are we supposed to re-implement all of + * that? Otherwise arguments in RUBYOPT will be parsed differently to if they were + * actually on the command line. JRuby just splits like we do. I also think that's what + * MRI does, but is this correct? + */ + + inputArgs.addAll(Arrays.asList(rubyoptVar.split("\\s+"))); + } + + inputArgs.addAll(Arrays.asList(args)); + + // Replace some contractions such as -rdir with -r dir + + final List outputArgs = new ArrayList<>(); + + for (String arg : inputArgs) { + if (arg.startsWith("-C") || arg.startsWith("-E") || arg.startsWith("-F") || arg.startsWith("-I") || arg.startsWith("-r")) { + outputArgs.add(arg.substring(0, 2)); + outputArgs.add(arg.substring(2)); + } else { + outputArgs.add(arg); + } + } + + return outputArgs; + } + + /** + * Print help information. + */ + private static void help(PrintStream out) { + out.println("Usage: ruby [switches] [--] [programfile] [arguments]"); + out.println(" -0[octal] specify record separator (\0, if no argument)"); + out.println(" -a autosplit mode with -n or -p (splits $_ into $F)"); + out.println(" -c check syntax only"); + out.println(" -Cdirectory cd to directory, before executing your script"); + out.println(" -d, --debug set debugging flags (set $DEBUG to true) and enable Debug module"); + out.println(" -e 'command' one line of script. Several -e's allowed. Omit [programfile]"); + out.println(" -Eex[:in] specify the default external and internal character encodings"); + out.println(" -Fpattern split() pattern for autosplit (-a)"); + out.println(" -i[extension] edit ARGV files in place (make backup if extension supplied)"); + out.println(" -Idirectory specify $LOAD_PATH directory (may be used more than once)"); + out.println(" -l enable line ending processing"); + out.println(" -n assume 'while gets(); ... end' loop around your script"); + out.println(" -p assume loop like -n but print line also like sed"); + out.println(" -rlibrary require the library, before executing your script"); + out.println(" -s enable some switch parsing for switches after script name"); + out.println(" -S look for the script using PATH environment variable"); + out.println(" -T[level=1] turn on tainting checks"); + out.println(" -v print version number, then turn on verbose mode"); + out.println(" -w turn warnings on for your script"); + out.println(" -W[level=2] set warning level; 0=silence, 1=medium, 2=verbose"); + out.println(" -x[directory] strip off text before #!ruby line and perhaps cd to directory"); + out.println(" --copyright print the copyright"); + out.println(" --version print the version"); + out.println("Extra rubytruffle switches:"); + out.println(" --home dir set the location of the Ruby Truffle installation (default . or $RUBY_TRUFFLE_HOME)"); + out.println(" --stdlib dir use a directory for the Ruby standard library"); + out.println(" --1.8 1.8 compatibility mode"); + out.println(" --1.9 1.9 compatibility mode (default)"); + out.println(" --2.0 2.0 compatibility mode"); + out.println(" --full-object-space enable full ObjectSpace#each_object and similar"); + out.println(" --no-debug disable debugging"); + out.println(" --no-trace disable tracing"); + out.println("Debugging rubytruffle switches:"); + out.println(" --no-cache-constant-lookup don't cache constant lookups"); + out.println(" --no-cache-method-calls don't cache method lookups"); + out.println(" --no-intrinsic-method-calls don't turn method calls into intrinsic nodes"); + out.println(" --no-jline don't use JLine"); + out.println(" --print-parse-tree print the result of parsing"); + out.println(" --print-executed-files print the name of files as they are executed"); + out.println(" --print-missing-intrinsics print method calls that don't have intrinsic nodes"); + out.println(" --print-spilt-instance-variables print each time a native-typed instance variable is spilt to the boxed array"); + out.println(" --print-uninitialized-calls print each time a method call is uninitialized"); + out.println(" --print-java-exceptions print Java exception back traces at the point of translating them to Ruby exceptions"); + out.println(" --print-ruby-exceptions print the Java exception back traces at the point of raising Ruby exceptions"); + out.println("Relevant environment variables:"); + out.println(" RUBYHOME location of the Ruby Truffle installation"); + out.println(" RUBYOPT extra command line arguments"); + out.println(" RUBYLIB list of colon separated paths to add to $LOAD_PATH"); + out.println(" PATH as RUBYLIB, if -S is used"); + } + + /** + * Print version information. + */ + private static void version(PrintStream out) { + out.printf("ruby (rubytruffle) dev [JVM %s]\n", System.getProperty("java.version")); + } + + /** + * Print copyright information. + */ + private static void copyright(PrintStream out) { + out.println("Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved."); + out.println("ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms."); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.shell/src/com/oracle/truffle/ruby/shell/Shell.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.shell/src/com/oracle/truffle/ruby/shell/Shell.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.shell; + +import java.io.*; + +import jline.console.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.ruby.nodes.core.*; +import com.oracle.truffle.ruby.parser.*; +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.configuration.*; +import com.oracle.truffle.ruby.runtime.core.array.*; + +/** + * The entry point class for RubyTruffle. Implements the MRI command line interface. + */ +public class Shell { + + /** + * Entry point method for Ruby both in batch and interactive mode. + */ + public static void main(String[] args) throws IOException { + // Parse the command line + + final CommandLineOptions options = CommandLineParser.parse(args); + + if (options == null) { + return; + } + + // Setup JLine + + ConsoleReader console = null; + + if (options.useJLine()) { + System.setProperty("jline.shutdownhook", "true"); + console = new ConsoleReader(); + console.setExpandEvents(false); + } + + // Override the home directory if RUBYHOME is set + + final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(options.getConfiguration()); + + if (System.getenv("RUBYHOME") != null) { + configurationBuilder.setStandardLibrary(System.getenv("RUBYHOME") + "/" + ConfigurationBuilder.JRUBY_STDLIB_JAR); + } + + // Use JLine for console input + + final ConsoleReader finalConsole = console; + + if (options.useJLine()) { + configurationBuilder.setInputReader(new InputReader() { + + @Override + public String readLine(String prompt) throws IOException { + return finalConsole.readLine(prompt); + } + + }); + } + + // Set up a context + + final RubyContext context = new RubyContext(new Configuration(configurationBuilder), new JRubyParser()); + + // Bring in core method nodes + + CoreMethodNodeManager.addMethods(context.getCoreLibrary().getObjectClass()); + + // Give the core library manager a chance to tweak some of those methods + + context.getCoreLibrary().initializeAfterMethodsAdded(); + + // Set program arguments + + for (String arg : options.getProgramArgs()) { + context.getCoreLibrary().getArgv().push(context.makeString(arg)); + } + + if (!options.getSwitchArgs().isEmpty()) { + context.implementationMessage("can't set -s switch arguments yet"); + } + + // Set the load path + + final RubyArray loadPath = (RubyArray) context.getCoreLibrary().getGlobalVariablesObject().getInstanceVariable("$:"); + + final String pathVar = System.getenv("PATH"); + + if (options.isImportFromPath() && pathVar != null) { + for (String path : pathVar.split(File.pathSeparator)) { + loadPath.push(context.makeString(path)); + } + } + + for (String path : options.getExtraLoadPath()) { + loadPath.push(context.makeString(path)); + } + + final String rubylibVar = System.getenv("RUBYLIB"); + + if (rubylibVar != null) { + for (String path : rubylibVar.split(File.pathSeparator)) { + loadPath.push(context.makeString(path)); + } + } + + if (context.getConfiguration().getStandardLibrary().endsWith(".jar")) { + String version = null; + + switch (configurationBuilder.getRubyVersion()) { + case RUBY_18: + version = "1.8"; + break; + case RUBY_19: + version = "1.9"; + break; + case RUBY_20: + version = "2.0"; + break; + case RUBY_21: + version = "2.0"; + break; + } + + loadPath.push(context.makeString("jar:file:" + context.getConfiguration().getStandardLibrary() + "!/META-INF/jruby.home/lib/ruby/" + version)); + + } else { + loadPath.push(context.makeString(context.getConfiguration().getStandardLibrary())); + } + + // Pre-required modules + + for (String feature : options.getPreRequires()) { + context.getFeatureManager().require(feature); + } + + // Check for other options that are not implemented yet + + if (options.getRecordSeparator() != -1) { + context.implementationMessage("record separator not implemented"); + } + + if (options.isAutosplit()) { + context.implementationMessage("autosplit not implemented"); + } + + if (options.getPreChangeDirectory() != null) { + context.implementationMessage("not able to change directory"); + } + + if (options.isLineEndingProcessing()) { + context.implementationMessage("line end processing not implemented"); + } + + if (options.isInPlaceEdit()) { + context.implementationMessage("in place editing not implemented"); + } + + if (options.isImplicitLoop() || options.isImplicitSedLoop()) { + context.implementationMessage("implicit loops not implemented"); + } + + if (options.isStripMessage()) { + context.implementationMessage("strip message -x option not implemented"); + } + + // Run the scripts, program file, or run the temporary version of IRB + + try { + if (!options.getCommandLineScripts().isEmpty()) { + final StringBuilder combinedScript = new StringBuilder(); + + for (String script : options.getCommandLineScripts()) { + combinedScript.append(script); + combinedScript.append("\n"); + } + + try { + final Source source = context.getSourceManager().get("-e", combinedScript.toString()); + if (options.isCheckSyntaxOnly()) { + context.getParser().parse(context, source, RubyParser.ParserContext.TOP_LEVEL, null); + System.out.println("Syntax OK"); + } else { + context.execute(context, source, RubyParser.ParserContext.TOP_LEVEL, context.getCoreLibrary().getMainObject(), null); + } + } catch (Exception e) { + e.printStackTrace(); + } + } else if (options.getProgramFile() != null) { + try { + if (options.isCheckSyntaxOnly()) { + final Source source = context.getSourceManager().get(options.getProgramFile()); + context.getParser().parse(context, source, RubyParser.ParserContext.TOP_LEVEL, null); + System.out.println("Syntax OK"); + } else { + context.loadFile(options.getProgramFile()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } else { + if (options.isCheckSyntaxOnly()) { + System.err.println("Can't check syntax in IRB mode"); + return; + } + + context.runShell(null, null); + } + } finally { + context.shutdown(); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/README Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,21 @@ +This is a configuration of the RubySpec set of specifications - +http://rubyspec.org. RubySpec is the specifications, and MSpec is the tool to +run them. + +Thanks to Brian Shirai and others who have worked on RubySpec. + +At the moment we have only configured the version 1.9 specs, and we only run +language and command line specs. + +In the `specs` directory (everything we do here will be in the `specs` +directory), you need to clone the MSpec and RubySpec Git repositories: + + $ git clone https://github.com/rubyspec/mspec.git + $ git --git-dir=mspec/.git --work-tree=mspec checkout 1343524a06466b7aa0c90798b7894454c8abce0f + $ git clone https://github.com/rubyspec/rubyspec.git + $ git --git-dir=rubyspec/.git --work-tree=rubyspec checkout 926e356b268fe32c67bec43a21565d727360a89b + +Then you can run MSpec to run RubySpec. We can run all of the harness in our +implementation, not just as an executable under test. + + $ ./rubytruffle mspec/bin/mspec run -t ./rubytruffle --config rubytruffle.mspec --excl-tag fails diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/rubytruffle --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/rubytruffle Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,20 @@ +#!/bin/bash + +# The command this file executes is what mx would execute, just taken out of +# the mx wrapper because it appears to interfere with MSpec, and we need a +# 'executable' (a shell script will do) to run. +# +# If this file isn't working for you try generating one for your setup. You +# will need to do this for example if your Java isn't 1.7.0u45. You can use +# the command below - the -v flag gives you the Java command, then just append +# "$@". +# +# $TRUFFLE_DIR/mxtool/mx -v --vm server-nograal ruby -ea -- --home $TRUFFLE_DIR "$@" + +TRUFFLE_DIR=../../.. + +$TRUFFLE_DIR/jdk1.7.0_45/product/bin/java \ + -server-nograal -d64 -ea \ + -cp $TRUFFLE_DIR/lib/jline-2.10.jar:$TRUFFLE_DIR/lib/jrubyparser-0.5.0.jar:$TRUFFLE_DIR/lib/jruby-stdlib-1.7.4.jar:$TRUFFLE_DIR/lib/jnr-posix-3.0.0.jar:$TRUFFLE_DIR/lib/jnr-constants-0.8.4.jar:$TRUFFLE_DIR/lib/jnr-ffi-1.0.4.jar:$TRUFFLE_DIR/lib/jffi-1.2.1.jar:$TRUFFLE_DIR/lib/jffi-1.2.1-native.jar:$TRUFFLE_DIR/lib/jnr-x86asm-1.0.2.jar:$TRUFFLE_DIR/lib/asm-4.0.jar:$TRUFFLE_DIR/lib/asm-analysis-4.0.jar:$TRUFFLE_DIR/lib/asm-commons-4.0.jar:$TRUFFLE_DIR/lib/asm-tree-4.0.jar:$TRUFFLE_DIR/lib/asm-util-4.0.jar:$TRUFFLE_DIR/graal/com.oracle.truffle.api/bin:$TRUFFLE_DIR/graal/com.oracle.truffle.ruby.runtime/bin:$TRUFFLE_DIR/graal/com.oracle.truffle.api.dsl/bin:$TRUFFLE_DIR/graal/com.oracle.truffle.ruby.nodes/bin:$TRUFFLE_DIR/graal/com.oracle.truffle.ruby.parser/bin:$TRUFFLE_DIR/graal/com.oracle.truffle.ruby.shell/bin \ + com.oracle.truffle.ruby.shell.Shell \ + --home $TRUFFLE_DIR "$@" diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/rubytruffle.mspec --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/rubytruffle.mspec Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,26 @@ +class MSpecScript + + Rubyspec = "rubyspec" + + set :command_line, [ + "rubyspec/command_line" + ] + + set :language, [ + "rubyspec/language" + ] + + set :tags_patterns, [ + [/rubyspec/, "tags"], + [/_spec.rb$/, "_tags.txt"] + ] + + MSpec.enable_feature :encoding + MSpec.enable_feature :continuation + MSpec.enable_feature :fiber + MSpec.enable_feature :fork + MSpec.enable_feature :generator + + set :files, get(:command_line) + get(:language) + +end diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_a_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_a_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,2 @@ +fails:The -a command line option runs the code in loop conditional on Kernel.gets() +fails:The -a command line option sets $-a diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_d_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_d_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,3 @@ +fails:The -d command line option sets $DEBUG to true +fails:The -d command line option sets $VERBOSE to true +fails:The -d command line option sets $-d to true diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_e_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_e_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,2 @@ +fails:The -e command line option with -n and a Fixnum range mimics an awk conditional by comparing an inclusive-end range with $. +fails:The -e command line option with -n and a Fixnum range mimics a sed conditional by comparing an exclusive-end range with $. diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_n_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_n_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,4 @@ +fails:The -n command line option runs the code in loop conditional on Kernel.gets() +fails:The -n command line option only evaluates BEGIN blocks once +fails:The -n command line option only evaluates END blocks once +fails:The -n command line option allows summing over a whole file diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_p_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_p_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,2 @@ +fails:The -p command line option runs the code in loop conditional on Kernel.gets() and prints $_ +fails:The -p command line option sets $-p diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_r_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_r_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,1 @@ +fails:The -r command line option requires the specified file diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_s_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_s_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,8 @@ +fails:The -s command line option when using -- to stop parsing sets the value to true without an explicit value +fails:The -s command line option when using -- to stop parsing parses single letter args into globals +fails:The -s command line option when using -- to stop parsing parses long args into globals +fails:The -s command line option when using -- to stop parsing converts extra dashes into underscores +fails:The -s command line option when running a script sets the value to true without an explicit value +fails:The -s command line option when running a script parses single letter args into globals +fails:The -s command line option when running a script parses long args into globals +fails:The -s command line option when running a script converts extra dashes into underscores diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_upper_e_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_upper_e_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,1 @@ +fails:ruby -E raises a RuntimeError if used with -U diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_upper_f_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_upper_f_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,1 @@ +fails:the -F command line option specifies the field separator pattern for -a diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_upper_i_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_upper_i_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,1 @@ +fails:The -I command line option adds the path to the load path ($:) diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_upper_u_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_upper_u_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,7 @@ +fails:ruby -U sets Encoding.default_internal to UTF-8 +fails:ruby -U does nothing different if specified multiple times +fails:ruby -U is overruled by Encoding.default_internal= +fails:ruby -U does not affect the default external encoding +fails:ruby -U does not affect the source encoding +fails:ruby -U raises a RuntimeError if used with -Eext:int +fails:ruby -U raises a RuntimeError if used with -E:int diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_upper_w_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_upper_w_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,3 @@ +fails:The -W command line option with 0 sets $VERBOSE to nil +fails:The -W command line option with 1 sets $VERBOSE to false +fails:The -W command line option with 2 sets $VERBOSE to true diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_v_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_v_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,1 @@ +fails:The -v command line option sets $VERBOSE to true diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_w_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_w_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,1 @@ +fails:The -w command line option sets $VERBOSE to true diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_x_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/command_line/dash_x_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,2 @@ +fails:The -x command line option runs code after the first /#!.*ruby.*/-ish line in target file +fails:The -x command line option needs to be reviewed for spec completeness diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/command_line/error_message_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/command_line/error_message_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,1 @@ +fails:The error message caused by an exception is not printed to stdout diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/BEGIN_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/BEGIN_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,4 @@ +fails:The BEGIN keyword runs first in a given code unit +fails:The BEGIN keyword runs multiple begins in FIFO order +fails:The BEGIN keyword runs in a shared scope +fails:The BEGIN keyword accesses variables outside the eval scope diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/alias_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/alias_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,11 @@ +fails:The alias keyword creates a new name for an existing method +fails:The alias keyword adds the new method to the list of methods +fails:The alias keyword adds the new method to the list of public methods +fails:The alias keyword overwrites an existing method with the target name +fails:The alias keyword is reversible +fails:The alias keyword operates on the object's metaclass when used in instance_eval +fails:The alias keyword operates on methods with splat arguments +fails:The alias keyword operates on methods with splat arguments on eigenclasses +fails:The alias keyword operates on methods with splat arguments defined in a superclass +fails:The alias keyword operates on methods with splat arguments defined in a superclass using text block for class eval +fails:The alias keyword is not allowed against Fixnum or String instances diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/array_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/array_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,4 @@ +fails:The unpacking splat operator (*) returns a new array containing the same values when applied to an array inside an empty array +fails:The unpacking splat operator (*) unpacks the start and count arguments in an array slice assignment +fails:Array literals [] treats splatted nil as no element +fails:The unpacking splat operator (*) when applied to a non-Array value attempts to coerce it to Array if the object respond_to?(:to_a) diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/block_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/block_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,67 @@ +fails:A block allows to define a block variable with the same name as the enclosing block +fails:A block taking |a| arguments assigns nil to the argument when no values are yielded +fails:A block taking |a| arguments does not call #to_ary to convert a single yielded object to an Array +fails:A block taking |a| arguments assigns the first value yielded to the argument +fails:A block taking |a, b| arguments assgins nil to the arguments when no values are yielded +fails:A block taking |a, b| arguments assigns one value yielded to the first argument +fails:A block taking |a, b| arguments destructures a splatted Array +fails:A block taking |a, b| arguments calls #to_ary to convert a single yielded object to an Array +fails:A block taking |a, b| arguments does not call #to_ary if the single yielded object is an Array +fails:A block taking |a, b| arguments does not call #to_ary if the object does not respond to #to_ary +fails:A block taking |a, b| arguments raises an TypeError if #to_ary does not return an Array +fails:A block taking |a, *b| arguments assigns 'nil' and '[]' to the arguments when no values are yielded +fails:A block taking |a, *b| arguments assigns all yielded values after the first to the rest argument +fails:A block taking |a, *b| arguments assigns 'nil' and '[]' to the arguments when a single, empty Array is yielded +fails:A block taking |a, *b| arguments assigns the element of a single element Array to the first argument +fails:A block taking |a, *b| arguments destructures a splatted Array +fails:A block taking |a, *b| arguments destructures a single Array value assigning the remaining values to the rest argument +fails:A block taking |a, *b| arguments calls #to_ary to convert a single yielded object to an Array +fails:A block taking |a, *b| arguments does not call #to_ary if the single yielded object is an Array +fails:A block taking |a, *b| arguments raises an TypeError if #to_ary does not return an Array +fails:A block taking |*| arguments does not call #to_ary if the single yielded object is an Array +fails:A block taking |*| arguments does not call #to_ary to convert a single yielded object to an Array +fails:A block taking |*a| arguments assigns all the values passed to the argument as an Array +fails:A block taking |*a| arguments assigns '[[]]' to the argument when passed an empty Array +fails:A block taking |*a| arguments assigns a single Array value passed to the argument by wrapping it in an Array +fails:A block taking |*a| arguments does not call #to_ary if the single yielded object is an Array +fails:A block taking |*a| arguments does not call #to_ary to convert a single yielded object to an Array +fails:A block taking |a, | arguments assigns nil to the argument when no values are yielded +fails:A block taking |a, | arguments assigns the argument the first value yielded +fails:A block taking |a, | arguments assigns the argument the first of several values yielded when it is an Array +fails:A block taking |a, | arguments assigns nil to the argument when passed an empty Array +fails:A block taking |a, | arguments assigns the argument the first element of the Array when passed a single Array +fails:A block taking |a, | arguments calls #to_ary to convert a single yielded object to an Array +fails:A block taking |a, | arguments does not call #to_ary if the single yielded object is an Array +fails:A block taking |a, | arguments raises an TypeError if #to_ary does not return an Array +fails:A block taking |(a, b)| arguments assigns nil to the arguments when yielded no values +fails:A block taking |(a, b)| arguments calls #to_ary to convert a single yielded object to an Array +fails:A block taking |(a, b)| arguments does not call #to_ary if the single yielded object is an Array +fails:A block taking |(a, b)| arguments does not call #to_ary if the object does not respond to #to_ary +fails:A block taking |(a, b)| arguments raises an TypeError if #to_ary does not return an Array +fails:A block taking |(a, b), c| arguments assigns nil to the arguments when yielded no values +fails:A block taking |(a, b), c| arguments destructures a single one-level Array value yielded +fails:A block taking |(a, b), c| arguments destructures a single multi-level Array value yielded +fails:A block taking |(a, b), c| arguments calls #to_ary to convert a single yielded object to an Array +fails:A block taking |(a, b), c| arguments does not call #to_ary if the single yielded object is an Array +fails:A block taking |(a, b), c| arguments does not call #to_ary if the object does not respond to #to_ary +fails:A block taking |(a, b), c| arguments raises an TypeError if #to_ary does not return an Array +fails:A block taking nested |a, (b, (c, d))| destructures a single multi-level Array value yielded +fails:A block taking nested |a, (b, (c, d))| destructures a single multi-level Array value yielded +fails:A block taking nested |a, ((b, c), d)| destructures a single multi-level Array value yielded +fails:A block taking nested |a, ((b, c), d)| destructures a single multi-level Array value yielded +fails:A block arguments with _ extracts arguments with _ +fails:Block-local variables override shadowed variables from the outer scope +fails:Post-args appear after a splat +fails:Post-args are required +fails:Post-args with required args gathers remaining args in the splat +fails:Post-args with required args has an empty splat when there are no remaining args +fails:Post-args with optional args gathers remaining args in the splat +fails:Post-args with optional args overrides the optional arg before gathering in the splat +fails:Post-args with optional args uses the required arg before the optional and the splat +fails:Post-args with optional args overrides the optional args from left to right before gathering the splat +fails:A block taking |(a, b)| arguments destructures a single Array value yielded +fails:A block taking |(a, b)| arguments destructures a single Array value yielded when shadowing an outer variable +fails:A block taking nested |a, (b, (c, d))| assigns nil to the arguments when yielded no values +fails:A block taking nested |a, (b, (c, d))| destructures separate yielded values +fails:A block taking nested |a, ((b, c), d)| assigns nil to the arguments when yielded no values +fails:A block taking nested |a, ((b, c), d)| destructures separate yielded values diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/break_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/break_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,3 @@ +fails:The break statement in a lambda created at the toplevel returns a value when invoking from the toplevel +fails:The break statement in a lambda created at the toplevel returns a value when invoking from a method +fails:The break statement in a lambda created at the toplevel returns a value when invoking from a block diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/case_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/case_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,12 @@ +fails:The 'case'-construct evaluates the body of the when clause matching the case target expression +fails:The 'case'-construct evaluates the body of the when clause whose array expression includes the case target expression +fails:The 'case'-construct evaluates the body of the when clause in left-to-right order if it's an array expression +fails:The 'case'-construct evaluates the body of the when clause whose range expression includes the case target expression +fails:The 'case'-construct expands arrays to lists of values +fails:The 'case'-construct concats arrays before expanding them +fails:The 'case'-construct never matches when clauses with no values +fails:The 'case'-construct works even if there's only one when statement +fails:The 'case'-construct with no target expression evaluates true as only 'true' when true is the first clause +fails:The 'case'-construct with no target expression evaluates false as only 'false' when false is the first clause +fails:The 'case'-construct with no target expression treats a literal array as its own when argument, rather than a list of arguments +fails:The 'case'-construct takes multiple expanded arrays diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/class_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/class_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,18 @@ +fails:A class definition has no class variables +fails:A class definition raises TypeError if the constant qualifying the class is nil +fails:A class definition raises TypeError if any constant qualifying the class is not a Module +fails:A class definition allows using self as the superclass if self is a class +fails:A class definition raises a TypeError if inheriting from a metaclass +fails:A class definition allows the declaration of class variables in the body +fails:A class definition stores instance variables defined in the class body in the class object +fails:A class definition allows the declaration of class variables in a class method +fails:A class definition allows the definition of class-level instance variables in a class method +fails:A class definition allows the declaration of class variables in an instance method +fails:A class definition returns the value of the last statement in the body +fails:An outer class definition contains the inner classes +fails:A class definition extending an object (sclass) raises a TypeError when trying to extend numbers +fails:A class definition extending an object (sclass) allows accessing the block of the original scope +fails:A class definition extending an object (sclass) can use return to cause the enclosing method to return +fails:Reopening a class raises a TypeError when superclasses mismatch +fails:Reopening a class adds new methods to subclasses +fails:class provides hooks calls inherited when a class is created diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/class_variable_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/class_variable_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,10 @@ +fails:A class variable can be accessed from a subclass +fails:A class variable is set in the superclass +fails:A class variable defined in a module can be accessed from classes that extend the module +fails:A class variable defined in a module is not defined in these classes +fails:A class variable defined in a module is only updated in the module a method defined in the module is used +fails:A class variable defined in a module is updated in the class when a Method defined in the class is used +fails:A class variable defined in a module can be accessed from modules that extend the module +fails:A class variable defined in a module is defined in the extended module +fails:A class variable defined in a module is not defined in the extending module +fails:A class variable defined in a module can be accessed inside the class using the module methods diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/constants_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/constants_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,45 @@ +fails:Literal (A::X) constant resolution sends #const_missing to the original class or module scope +fails:Literal (A::X) constant resolution raises a TypeError if a non-class or non-module qualifier is given +fails:Literal (A::X) constant resolution with statically assigned constants does not search the singleton class of the class or module +fails:Literal (A::X) constant resolution with dynamically assigned constants does not search the singleton class of the class or module +fails:Literal (A::X) constant resolution with dynamically assigned constants evaluates the right hand side before evaluating a constant path +fails:Constant resolution within methods sends #const_missing to the original class or module scope +fails:Constant resolution within methods with statically assigned constants searches the lexical scope of the method not the receiver's immediate class +fails:Constant resolution within methods with statically assigned constants searches the lexical scope of a singleton method +fails:Constant resolution within methods with statically assigned constants searches Object as a lexical scope only if Object is explicitly opened +fails:Constant resolution within methods with dynamically assigned constants searches the immediate class or module scope first +fails:Constant resolution within methods with dynamically assigned constants searches the superclass before a module included in the superclass +fails:Constant resolution within methods with dynamically assigned constants searches the lexical scope of the method not the receiver's immediate class +fails:Constant resolution within methods with dynamically assigned constants searches the lexical scope of a singleton method +fails:Constant resolution within methods with dynamically assigned constants does not search the lexical scope of the caller +fails:Constant resolution within methods with dynamically assigned constants searches the lexical scope of a block +fails:Constant resolution within methods with dynamically assigned constants searches Object as a lexical scope only if Object is explicitly opened +fails:Constant resolution within methods with ||= assignes constant if previously undefined +fails:Module#private_constant marked constants remain private even when updated +fails:Module#private_constant marked constants in a module cannot be accessed from outside the module +fails:Module#private_constant marked constants in a module cannot be reopened as a module +fails:Module#private_constant marked constants in a module cannot be reopened as a class +fails:Module#private_constant marked constants in a module is not defined? with A::B form +fails:Module#private_constant marked constants in a module can be accessed from lexical scope +fails:Module#private_constant marked constants in a module is defined? from lexical scope +fails:Module#private_constant marked constants in a class cannot be accessed from outside the class +fails:Module#private_constant marked constants in a class cannot be reopened as a module +fails:Module#private_constant marked constants in a class cannot be reopened as a class +fails:Module#private_constant marked constants in a class is not defined? with A::B form +fails:Module#private_constant marked constants in a class can be accessed from lexical scope +fails:Module#private_constant marked constants in Object cannot be accessed using ::Const form +fails:Module#private_constant marked constants in Object is not defined? using ::Const form +fails:Module#public_constant marked constants in a module can be accessed from outside the module +fails:Module#public_constant marked constants in a module is defined? with A::B form +fails:Module#public_constant marked constants in a class can be accessed from outside the class +fails:Module#public_constant marked constants in a class is defined? with A::B form +fails:Module#public_constant marked constants in Object can be accessed using ::Const form +fails:Module#public_constant marked constants in Object is defined? using ::Const form +fails:Module#private_constant marked constants in a class is defined? from lexical scope +fails:Literal (A::X) constant resolution with statically assigned constants searches a module included in the superclass +fails:Constant resolution within methods with statically assigned constants searches a module included in the superclass +fails:Constant resolution within methods with statically assigned constants searches the superclass chain +fails:Literal (A::X) constant resolution with statically assigned constants searches Object if no class or module qualifier is given +fails:Literal (A::X) constant resolution with statically assigned constants searches Object after searching other scopes +fails:Constant resolution within methods with statically assigned constants searches the superclass chain +fails:Literal (A::X) constant resolution with statically assigned constants searches the superclass chain diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/def_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/def_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,28 @@ +fails:Defining an 'initialize' method sets the method's visibility to private +fails:Defining an 'initialize_copy' method sets the method's visibility to private +fails:An instance method with a default argument assigns an empty Array to an unused splat argument +fails:An instance method with a default argument prefers to assign to a default argument when there are no required arguments +fails:An instance method with a default argument does not evaluate the default when passed a value and a * argument +fails:A singleton method definition raises RuntimeError if frozen +fails:Redefining a singleton method does not inherit a previously set visibility +fails:Redefining a singleton method does not inherit a previously set visibility +fails:A method defined with extreme default arguments may use an fcall as a default +fails:A method defined with extreme default arguments may use preceding arguments as defaults +fails:A method defined with extreme default arguments may use a lambda as a default +fails:A singleton method defined with extreme default arguments may use an fcall as a default +fails:A singleton method defined with extreme default arguments may use preceding arguments as defaults +fails:A singleton method defined with extreme default arguments may use a lambda as a default +fails:A method definition inside a metaclass scope can create a class method +fails:A method definition inside a metaclass scope can create a singleton method +fails:A method definition inside a metaclass scope raises RuntimeError if frozen +fails:A nested method definition creates an instance method when evaluated in an instance method +fails:A nested method definition creates a class method when evaluated in a class method +fails:A nested method definition creates a singleton method when evaluated in the metaclass of an instance +fails:A method definition inside an instance_eval creates a singleton method +fails:A method definition inside an instance_eval creates a singleton method when evaluated inside a metaclass +fails:A method definition inside an instance_eval creates a class method when the receiver is a class +fails:A method definition in an eval creates an instance method +fails:A method definition in an eval creates a class method +fails:A method definition in an eval creates a singleton method +fails:a method definition that sets more than one default parameter all to the same value assigns them all the same object by default +fails:The def keyword within a closure looks outside the closure for the visibility diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/defined_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/defined_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,48 @@ +fails:The defined? keyword when called with a method name having a module as receiver returns nil if the method is private +fails:The defined? keyword when called with a method name having a module as receiver returns nil if the method is protected +fails:The defined? keyword when called with a method name having a local variable as receiver calls #respond_to_missing? +fails:The defined? keyword for an expression returns nil for an expression with !~ and an undefined method +fails:The defined? keyword for an expression returns 'method' for an expression with '!~' +fails:The defined? keyword for an expression with logical connectives returns nil for an expression with '!' and an unset class variable +fails:The defined? keyword for an expression with logical connectives returns nil for an expression with 'not' and an unset class variable +fails:The defined? keyword for an expression with logical connectives returns nil for an expression with '!' and an unset global variable +fails:The defined? keyword for an expression with logical connectives returns nil for an expression with '!' and an unset instance variable +fails:The defined? keyword for an expression with logical connectives returns nil for an expression with 'not' and an unset global variable +fails:The defined? keyword for an expression with logical connectives returns nil for an expression with 'not' and an unset instance variable +fails:The defined? keyword for variables returns nil for a global variable that has not been read +fails:The defined? keyword for variables returns nil for a global variable that has been read but not assigned to +fails:The defined? keyword for variables when a String does not match a Regexp returns nil for $& +fails:The defined? keyword for variables when a String does not match a Regexp returns nil for $` +fails:The defined? keyword for variables when a String does not match a Regexp returns nil for $' +fails:The defined? keyword for variables when a String does not match a Regexp returns nil for $+ +fails:The defined? keyword for variables when a String matches a Regexp returns 'global-variable' for $& +fails:The defined? keyword for variables when a String matches a Regexp returns 'global-variable' for $` +fails:The defined? keyword for variables when a String matches a Regexp returns 'global-variable' for $' +fails:The defined? keyword for variables when a String matches a Regexp returns 'global-variable' for $+ +fails:The defined? keyword for variables when a String matches a Regexp returns 'global-variable' for the capture references +fails:The defined? keyword for variables when a Regexp does not match a String returns nil for $& +fails:The defined? keyword for variables when a Regexp does not match a String returns nil for $` +fails:The defined? keyword for variables when a Regexp does not match a String returns nil for $' +fails:The defined? keyword for variables when a Regexp does not match a String returns nil for $+ +fails:The defined? keyword for variables when a Regexp matches a String returns 'global-variable' for $& +fails:The defined? keyword for variables when a Regexp matches a String returns 'global-variable' for $` +fails:The defined? keyword for variables when a Regexp matches a String returns 'global-variable' for $' +fails:The defined? keyword for variables when a Regexp matches a String returns 'global-variable' for $+ +fails:The defined? keyword for variables when a Regexp matches a String returns 'global-variable' for the capture references +fails:The defined? keyword for a scoped constant returns nil when an undefined constant is scoped to a defined constant +fails:The defined? keyword for a top-level scoped constant returns nil when an undefined constant is scoped to a defined constant +fails:The defined? keyword for super returns nil when a superclass undef's the method +fails:The defined? keyword for super for a method taking no arguments returns 'super' from a block when a superclass method exists +fails:The defined? keyword for super for a method taking no arguments returns 'super' from a #define_method when a superclass method exists +fails:The defined? keyword for super for a method taking no arguments returns 'super' from a block in a #define_method when a superclass method exists +fails:The defined? keyword for super for a method taking no arguments returns 'super' when the method exists in a supermodule +fails:The defined? keyword for super for a method taking arguments returns 'super' when a superclass method exists +fails:The defined? keyword for super for a method taking arguments returns 'super' from a block when a superclass method exists +fails:The defined? keyword for super for a method taking arguments returns 'super' from a #define_method when a superclass method exists +fails:The defined? keyword for super for a method taking arguments returns 'super' from a block in a #define_method when a superclass method exists +fails:The defined? keyword for super within an included module's method returns 'super' when a superclass method exists in the including hierarchy +fails:The defined? keyword for instance variables returns nil if not assigned +fails:The defined? keyword for variables when a String does not match a Regexp returns nil for $1-$9 +fails:The defined? keyword for variables when a String matches a Regexp returns nil for non-captures +fails:The defined? keyword for variables when a Regexp does not match a String returns nil for $1-$9 +fails:The defined? keyword for variables when a Regexp matches a String returns nil for non-captures diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/encoding_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/encoding_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,14 @@ +fails:The __ENCODING__ pseudo-variable is an instance of Encoding +fails:The __ENCODING__ pseudo-variable is US-ASCII by default +fails:The __ENCODING__ pseudo-variable is the evaluated strings's one inside an eval +fails:The __ENCODING__ pseudo-variable is the encoding specified by a magic comment inside an eval +fails:The __ENCODING__ pseudo-variable is the encoding specified by a magic comment in the file +fails:The __ENCODING__ pseudo-variable is Encoding::ASCII_8BIT when the interpreter is invoked with -Ka +fails:The __ENCODING__ pseudo-variable is Encoding::ASCII_8BIT when the interpreter is invoked with -KA +fails:The __ENCODING__ pseudo-variable is Encoding::EUC_JP when the interpreter is invoked with -Ke +fails:The __ENCODING__ pseudo-variable is Encoding::EUC_JP when the interpreter is invoked with -KE +fails:The __ENCODING__ pseudo-variable is Encoding::UTF_8 when the interpreter is invoked with -Ku +fails:The __ENCODING__ pseudo-variable is Encoding::UTF_8 when the interpreter is invoked with -KU +fails:The __ENCODING__ pseudo-variable is Encoding::Windows_31J when the interpreter is invoked with -Ks +fails:The __ENCODING__ pseudo-variable is Encoding::Windows_31J when the interpreter is invoked with -KS +fails:The __ENCODING__ pseudo-variable raises a SyntaxError if assigned to diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/ensure_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/ensure_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,2 @@ +fails:An ensure block inside a begin block is executed when an exception is raised in it's corresponding begin block +fails:An ensure block inside a method is executed when an exception is raised in the method diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/execution_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/execution_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,2 @@ +fails:`` returns the output of the executed sub-process +fails:%x is the same as `` diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/file_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/file_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,3 @@ +fails:The __FILE__ pseudo-variable equals (eval) inside an eval +fails:The __FILE__ pseudo-variable equals the absolute path of a file loaded by an absolute path +fails:The __FILE__ pseudo-variable equals the absolute path of a file loaded by a relative path diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/for_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/for_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,6 @@ +fails:The for expression iterates over an Hash passing each key-value pair to the block +fails:The for expression allows a class variable as an iterator name +fails:The for expression yields only as many values as there are arguments +fails:The for expression executes code in containing variable scope +fails:The for expression executes code in containing variable scope with 'do' +fails:The for expression returns expr diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/hash_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/hash_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,1 @@ +fails:Hash literal freezes string keys on initialization diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/line_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/line_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,1 @@ +fails:The __LINE__ pseudo-variable equals the line number of the text in a loaded file diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/literal_lambda_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/literal_lambda_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,4 @@ +fails:->(){} assigns the given block to the parameter prefixed with an ampersand if such a parameter exists +fails:->(){} sets parameters appropriately when a combination of parameter types is given between the parenthesis +fails:->(){} uses lambda's 'rigid' argument handling +fails:->(){} evaluates constants as normal blocks do diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/magic_comment_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/magic_comment_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,8 @@ +fails:Magic comment is optional +fails:Magic comment determines __ENCODING__ +fails:Magic comment is case-insensitive +fails:Magic comment must be at the first line +fails:Magic comment must be the first token of the line +fails:Magic comment can be after the shebang +fails:Magic comment can take Emacs style +fails:Magic comment can take vim style diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/match_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/match_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,2 @@ +fails:The !~ operator evaluates as a call to !~ +fails:The =~ operator calls the =~ method diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/metaclass_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/metaclass_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,16 @@ +fails:self in a metaclass body (class << obj) is TrueClass for true +fails:self in a metaclass body (class << obj) is FalseClass for false +fails:self in a metaclass body (class << obj) is NilClass for nil +fails:self in a metaclass body (class << obj) raises a TypeError for numbers +fails:self in a metaclass body (class << obj) raises a TypeError for symbols +fails:self in a metaclass body (class << obj) is a singleton Class instance +fails:A constant on a metaclass can be accessed via const_get +fails:A constant on a metaclass cannot be accessed via object::CONST +fails:A constant on a metaclass raises a NameError for anonymous_module::CONST +fails:A constant on a metaclass appears in the metaclass constant list +fails:A constant on a metaclass does not appear in the object's class constant list +fails:A constant on a metaclass is not preserved when the object is duped +fails:A constant on a metaclass is preserved when the object is cloned +fails:calling methods on the metaclass calls a method on the instance's metaclass +fails:calling methods on the metaclass calls a method in deeper chains of metaclasses +fails:calling methods on the metaclass calls a method defined on the metaclass of the metaclass diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/module_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/module_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,7 @@ +fails:The module keyword reopens a module included in Object +fails:The module keyword raises a TypeError if the constant is a Class +fails:The module keyword raises a TypeError if the constant is a String +fails:The module keyword raises a TypeError if the constant is a Fixnum +fails:The module keyword raises a TypeError if the constant is nil +fails:The module keyword raises a TypeError if the constant is true +fails:The module keyword raises a TypeError if the constant is false diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/next_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/next_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,9 @@ +fails:The next statement from within the block returns the argument passed +fails:The next statement from within the block returns to the invoking method, with the specified value +fails:The next statement from within the block returns to the currently yielding method in case of chained calls +fails:Assignment via next assigns objects +fails:Assignment via next assigns splatted objects +fails:Assignment via next assigns objects to a splatted reference +fails:Assignment via next assigns splatted objects to a splatted reference via a splatted yield +fails:Assignment via next assigns objects to multiple variables +fails:Assignment via next assigns splatted objects to multiple variables diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/precedence_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/precedence_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,2 @@ +fails:Operators + - have higher precedence than >> << +fails:Operators + - are left-associative diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/predefined/data_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/predefined/data_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,6 @@ +fails:The DATA constant exists when the main script contains __END__ +fails:The DATA constant does not exist when the main script contains no __END__ +fails:The DATA constant does not exist when an included file has a __END__ +fails:The DATA constant does not change when an included files also has a __END__ +fails:The DATA constant is included in an otherwise empty file +fails:The DATA constant succeeds in locking the file DATA came from diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/predefined_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/predefined_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,108 @@ +fails:Predefined global $~ is set to contain the MatchData object of the last match if successful +fails:Predefined global $~ is set to nil if the last match was unsuccessful +fails:Predefined global $~ is set at the method-scoped level rather than block-scoped +fails:Predefined global $~ raises an error if assigned an object not nil or instanceof MatchData +fails:Predefined global $~ changes the value of derived capture globals when assigned +fails:Predefined global $~ changes the value of the derived preceding match global +fails:Predefined global $~ changes the value of the derived following match global +fails:Predefined global $~ changes the value of the derived full match global +fails:Predefined global $& is equivalent to MatchData#[0] on the last match $~ +fails:Predefined global $& sets the encoding to the encoding of the source String +fails:Predefined global $` is equivalent to MatchData#pre_match on the last match $~ +fails:Predefined global $` sets the encoding to the encoding of the source String +fails:Predefined global $` sets an empty result to the encoding of the source String +fails:Predefined global $' is equivalent to MatchData#post_match on the last match $~ +fails:Predefined global $' sets the encoding to the encoding of the source String +fails:Predefined global $' sets an empty result to the encoding of the source String +fails:Predefined global $+ is equivalent to $~.captures.last +fails:Predefined global $+ captures the last non nil capture +fails:Predefined global $+ sets the encoding to the encoding of the source String +fails:Predefined globals $1..N are equivalent to $~[N] +fails:Predefined globals $1..N are nil unless a match group occurs +fails:Predefined globals $1..N sets the encoding to the encoding of the source String +fails:Predefined global $stdout is the same as $DEFAULT_OUTPUT from 'English' library +fails:Predefined global $stdout raises TypeError error if assigned to nil +fails:Predefined global $stdout raises TypeError error if assigned to object that doesn't respond to #write +fails:Predefined global $! remains nil after a failed core class "checked" coercion against a class that defines method_missing +fails:Predefined global $/ changes $-0 +fails:Predefined global $/ does not call #to_str to convert the object to a String +fails:Predefined global $/ raises a TypeError if assigned a Fixnum +fails:Predefined global $/ raises a TypeError if assigned a boolean +fails:Predefined global $-0 changes $/ +fails:Predefined global $-0 does not call #to_str to convert the object to a String +fails:Predefined global $-0 raises a TypeError if assigned a Fixnum +fails:Predefined global $-0 raises a TypeError if assigned a boolean +fails:Predefined global $, raises TypeError if assigned a non-String +fails:Predefined global $_ is set to the last line read by e.g. StringIO#gets +fails:Predefined global $_ is set at the method-scoped level rather than block-scoped +fails:Predefined global $_ is Thread-local +fails:Execution variable $: does not include '.' when the taint check level > 1 +fails:Execution variable $: is the same object as $LOAD_PATH and $-I +fails:Execution variable $: is read-only +fails:Global variable $" is read-only +fails:Global variable $< is read-only +fails:Global variable $FILENAME is read-only +fails:Global variable $? is read-only +fails:Global variable $? is thread-local +fails:Global variable $-a is read-only +fails:Global variable $-l is read-only +fails:Global variable $-p is read-only +fails:Global variable $-d is an alias of $DEBUG +fails:Global variable $-v is an alias of $VERBOSE +fails:Global variable $-w is an alias of $VERBOSE +fails:Global variable $0 raises a TypeError when not given an object that can be coerced to a String +fails:The predefined standard objects includes ARGF +fails:The predefined global constants includes TRUE +fails:The predefined global constants includes FALSE +fails:The predefined global constants includes NIL +fails:The predefined global constants includes STDIN +fails:The predefined global constants includes STDOUT +fails:The predefined global constants includes STDERR +fails:The predefined global constants includes RUBY_RELEASE_DATE +fails:The predefined global constants includes TOPLEVEL_BINDING +fails:Processing RUBYOPT adds the -I path to $LOAD_PATH +fails:Processing RUBYOPT sets $DEBUG to true for '-d' +fails:Processing RUBYOPT prints the version number for '-v' +fails:Processing RUBYOPT sets $VERBOSE to true for '-w' +fails:Processing RUBYOPT sets $VERBOSE to true for '-W' +fails:Processing RUBYOPT sets $VERBOSE to nil for '-W0' +fails:Processing RUBYOPT sets $VERBOSE to false for '-W1' +fails:Processing RUBYOPT sets $VERBOSE to true for '-W2' +fails:Processing RUBYOPT requires the file for '-r' +fails:Processing RUBYOPT raises a RuntimeError for '-a' +fails:Processing RUBYOPT raises a RuntimeError for '-p' +fails:Processing RUBYOPT raises a RuntimeError for '-n' +fails:Processing RUBYOPT raises a RuntimeError for '-y' +fails:Processing RUBYOPT raises a RuntimeError for '-c' +fails:Processing RUBYOPT raises a RuntimeError for '-s' +fails:Processing RUBYOPT raises a RuntimeError for '-h' +fails:Processing RUBYOPT raises a RuntimeError for '--help' +fails:Processing RUBYOPT raises a RuntimeError for '-l' +fails:Processing RUBYOPT raises a RuntimeError for '-S' +fails:Processing RUBYOPT raises a RuntimeError for '-e' +fails:Processing RUBYOPT raises a RuntimeError for '-i' +fails:Processing RUBYOPT raises a RuntimeError for '-x' +fails:Processing RUBYOPT raises a RuntimeError for '-C' +fails:Processing RUBYOPT raises a RuntimeError for '-X' +fails:Processing RUBYOPT raises a RuntimeError for '-F' +fails:Processing RUBYOPT raises a RuntimeError for '-0' +fails:Processing RUBYOPT raises a RuntimeError for '--copyright' +fails:Processing RUBYOPT raises a RuntimeError for '--version' +fails:Processing RUBYOPT raises a RuntimeError for '--yydebug' +fails:The predefined global constant STDERR has nil for the external encoding despite Encoding.default_external being changed +fails:The predefined global constant STDERR has the encodings set by #set_encoding +fails:The predefined global constant ARGV contains Strings encoded in locale Encoding +fails:The predefined global constant STDERR has nil for the internal encoding despite Encoding.default_internal being changed +fails:The predefined global constant STDERR has nil for the internal encoding +fails:The predefined global constant STDERR has nil for the external encoding +fails:The predefined global constant STDOUT has nil for the internal encoding despite Encoding.default_internal being changed +fails:The predefined global constant STDOUT has nil for the internal encoding +fails:The predefined global constant STDOUT has the encodings set by #set_encoding +fails:The predefined global constant STDOUT has nil for the external encoding despite Encoding.default_external being changed +fails:The predefined global constant STDOUT has nil for the external encoding +fails:The predefined global constant STDIN has nil for the internal encoding despite Encoding.default_internal being changed +fails:The predefined global constant STDIN has nil for the internal encoding +fails:The predefined global constant STDIN retains the encoding set by #set_encoding when Encoding.default_external is changed +fails:The predefined global constant STDIN has the encodings set by #set_encoding +fails:The predefined global constant STDIN has the same external encoding as Encoding.default_external when that encoding is changed +fails:The predefined global constant STDIN has the same external encoding as Encoding.default_external diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/private_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/private_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,1 @@ +fails:The private keyword is overridden when a new class is opened diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/proc_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/proc_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,18 @@ +fails:A Proc taking zero arguments raises an ArgumentErro if a value is passed +fails:A Proc taking || arguments raises an ArgumentError if a value is passed +fails:A Proc taking |a| arguments does not call #to_ary to convert a single passed object to an Array +fails:A Proc taking |a| arguments raises an ArgumentError if no value is passed +fails:A Proc taking |a, b| arguments raises an ArgumentError if passed no values +fails:A Proc taking |a, b| arguments raises an ArgumentError if passed one value +fails:A Proc taking |a, b| arguments does not call #to_ary to convert a single passed object to an Array +fails:A Proc taking |a, *b| arguments raises an ArgumentError if passed no values +fails:A Proc taking |a, *b| arguments does not call #to_ary to convert a single passed object to an Array +fails:A Proc taking |*| arguments does not call #to_ary to convert a single passed object to an Array +fails:A Proc taking |*a| arguments does not call #to_ary to convert a single passed object to an Array +fails:A Proc taking |a, | arguments raises an ArgumentError when passed no values +fails:A Proc taking |a, | arguments raises an ArgumentError when passed more than one value +fails:A Proc taking |a, | arguments does not call #to_ary to convert a single passed object to an Array +fails:A Proc taking |(a, b)| arguments raises an ArgumentError when passed no values +fails:A Proc taking |(a, b)| arguments calls #to_ary to convert a single passed object to an Array +fails:A Proc taking |(a, b)| arguments raises an TypeError if #to_ary does not return an Array +fails:A Proc taking |(a, b)| arguments destructures a single Array value yielded diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/redo_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/redo_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,3 @@ +fails:The redo statement restarts block execution if used within block +fails:The redo statement re-executes the closest loop +fails:The redo statement re-executes the last step in enumeration diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/regexp/anchors_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/regexp/anchors_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,1 @@ +fails:Regexps with anchors supports B (non-word-boundary) diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/regexp/back-references_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/regexp/back-references_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,4 @@ +fails:Regexps with back-references saves match data in the $~ pseudo-global variable +fails:Regexps with back-references saves captures in numbered $[1-9] variables +fails:Regexps with back-references will not clobber capture variables across threads +fails:Regexps with back-references resets nested backreference before match of outer subexpression diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/regexp/character_classes_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/regexp/character_classes_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,68 @@ +fails:Regexp with character classes supports [] (character class) +fails:Regexp with character classes supports [[:alpha:][:digit:][:etc:]] (predefined character classes) +fails:Regexp with character classes matches ASCII characters with [[:ascii:]] +fails:Regexp with character classes matches Unicode letter characters with [[:alnum:]] +fails:Regexp with character classes matches Unicode digits with [[:alnum:]] +fails:Regexp with character classes doesn't match Unicode control characters with [[:alnum:]] +fails:Regexp with character classes doesn't match Unicode punctuation characters with [[:alnum:]] +fails:Regexp with character classes matches Unicode letter characters with [[:alpha:]] +fails:Regexp with character classes doesn't match Unicode digits with [[:alpha:]] +fails:Regexp with character classes doesn't match Unicode control characters with [[:alpha:]] +fails:Regexp with character classes doesn't match Unicode punctuation characters with [[:alpha:]] +fails:Regexp with character classes matches Unicode space characters with [[:blank:]] +fails:Regexp with character classes matches Unicode control characters with [[:cntrl:]] +fails:Regexp with character classes matches Unicode digits with [[:digit:]] +fails:Regexp with character classes matches Unicode letter characters with [[:graph:]] +fails:Regexp with character classes matches Unicode digits with [[:graph:]] +fails:Regexp with character classes matches Unicode marks with [[:graph:]] +fails:Regexp with character classes matches Unicode punctuation characters with [[:graph:]] +fails:Regexp with character classes match Unicode format characters with [[:graph:]] +fails:Regexp with character classes match Unicode private-use characters with [[:graph:]] +fails:Regexp with character classes matches Unicode lowercase letter characters with [[:lower:]] +fails:Regexp with character classes matches Unicode lowercase letter characters with [[:print:]] +fails:Regexp with character classes matches Unicode uppercase letter characters with [[:print:]] +fails:Regexp with character classes matches Unicode title-case characters with [[:print:]] +fails:Regexp with character classes matches Unicode digits with [[:print:]] +fails:Regexp with character classes matches Unicode marks with [[:print:]] +fails:Regexp with character classes matches Unicode punctuation characters with [[:print:]] +fails:Regexp with character classes match Unicode format characters with [[:print:]] +fails:Regexp with character classes match Unicode private-use characters with [[:print:]] +fails:Regexp with character classes matches Unicode Pc characters with [[:punct:]] +fails:Regexp with character classes matches Unicode Pd characters with [[:punct:]] +fails:Regexp with character classes matches Unicode Ps characters with [[:punct:]] +fails:Regexp with character classes matches Unicode Pe characters with [[:punct:]] +fails:Regexp with character classes matches Unicode Pi characters with [[:punct:]] +fails:Regexp with character classes matches Unicode Pf characters with [[:punct:]] +fails:Regexp with character classes matches Unicode Pf characters with [[:punct:]] +fails:Regexp with character classes matches Unicode Po characters with [[:punct:]] +fails:Regexp with character classes matches Unicode Zs characters with [[:space:]] +fails:Regexp with character classes matches Unicode Zl characters with [[:space:]] +fails:Regexp with character classes matches Unicode Zp characters with [[:space:]] +fails:Regexp with character classes matches Unicode uppercase characters with [[:upper:]] +fails:Regexp with character classes doesn't match Unicode letter characters [^a-fA-F] with [[:xdigit:]] +fails:Regexp with character classes matches Unicode letter characters [a-fA-F] with [[:xdigit:]] +fails:Regexp with character classes matches Unicode lowercase characters with [[:word:]] +fails:Regexp with character classes matches Unicode uppercase characters with [[:word:]] +fails:Regexp with character classes matches Unicode title-case characters with [[:word:]] +fails:Regexp with character classes matches Unicode decimal digits with [[:word:]] +fails:Regexp with character classes matches Unicode marks with [[:word:]] +fails:Regexp with character classes match Unicode Nl characters with [[:word:]] +fails:Regexps with anchors supports ^ (line start anchor) +fails:Regexp with character classes doesn't matches Unicode marks with [[:alnum:]] +fails:Regexp with character classes doesn't match Unicode lowercase letter characters with [[:punct:]] +fails:Regexp with character classes doesn't match Unicode uppercase letter characters with [[:punct:]] +fails:Regexp with character classes doesn't match Unicode title-case characters with [[:punct:]] +fails:Regexp with character classes doesn't match Unicode digits with [[:punct:]] +fails:Regexp with character classes doesn't match Unicode marks with [[:punct:]] +fails:Regexp with character classes doesn't match Unicode format characters with [[:punct:]] +fails:Regexp with character classes doesn't match Unicode private-use characters with [[:punct:]] +fails:Regexp with character classes doesn't match Unicode lowercase characters with [[:upper:]] +fails:Regexp with character classes doesn't match Unicode title-case characters with [[:upper:]] +fails:Regexp with character classes doesn't match Unicode digits with [[:upper:]] +fails:Regexp with character classes doesn't match Unicode marks with [[:upper:]] +fails:Regexp with character classes doesn't match Unicode punctuation characters with [[:upper:]] +fails:Regexp with character classes doesn't match Unicode control characters with [[:upper:]] +fails:Regexp with character classes doesn't match Unicode format characters with [[:upper:]] +fails:Regexp with character classes doesn't match Unicode private-use characters with [[:upper:]] +fails:Regexps with escape characters support \x (hex characters) +fails:Regexps with escape characters support \c (control characters) diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/regexp/encoding_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/regexp/encoding_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,23 @@ +fails:Regexps with encoding modifiers supports /e (EUC encoding) +fails:Regexps with encoding modifiers supports /e (EUC encoding) with interpolation +fails:Regexps with encoding modifiers supports /e (EUC encoding) with interpolation /o +fails:Regexps with encoding modifiers uses EUC-JP as /e encoding +fails:Regexps with encoding modifiers preserves EUC-JP as /e encoding through interpolation +fails:Regexps with encoding modifiers supports /n (No encoding) +fails:Regexps with encoding modifiers supports /n (No encoding) with interpolation +fails:Regexps with encoding modifiers supports /n (No encoding) with interpolation /o +fails:Regexps with encoding modifiers uses US-ASCII as /n encoding if all chars are 7-bit +fails:Regexps with encoding modifiers uses ASCII-8BIT as /n encoding if not all chars are 7-bit +fails:Regexps with encoding modifiers preserves US-ASCII as /n encoding through interpolation if all chars are 7-bit +fails:Regexps with encoding modifiers preserves ASCII-8BIT as /n encoding through interpolation if all chars are 7-bit +fails:Regexps with encoding modifiers supports /s (Windows_31J encoding) +fails:Regexps with encoding modifiers supports /s (Windows_31J encoding) with interpolation +fails:Regexps with encoding modifiers supports /s (Windows_31J encoding) with interpolation and /o +fails:Regexps with encoding modifiers uses Windows-31J as /s encoding +fails:Regexps with encoding modifiers preserves Windows-31J as /s encoding through interpolation +fails:Regexps with encoding modifiers supports /u (UTF8 encoding) +fails:Regexps with encoding modifiers supports /u (UTF8 encoding) with interpolation +fails:Regexps with encoding modifiers supports /u (UTF8 encoding) with interpolation and /o +fails:Regexps with encoding modifiers uses UTF-8 as /u encoding +fails:Regexps with encoding modifiers preserves UTF-8 as /u encoding through interpolation +fails:Regexps with encoding modifiers selects last of multiple encoding specifiers diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/regexp/escapes_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/regexp/escapes_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,2 @@ +fails:Regexps with escape characters support \x (hex characters) +fails:Regexps with escape characters support \c (control characters) diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/regexp/grouping_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/regexp/grouping_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,1 @@ +fails:Regexps with grouping raise a SyntaxError when parentheses aren't balanced diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/regexp/interpolation_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/regexp/interpolation_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,7 @@ +fails:Regexps with interpolation allows interpolation of literal regexps +fails:Regexps with interpolation allows interpolation of any class that responds to to_s +fails:Regexps with interpolation allows interpolation which mixes modifiers +fails:Regexps with interpolation gives precedence to escape sequences over substitution +fails:Regexps with interpolation throws RegexpError for malformed interpolation +fails:Regexps with interpolation allows interpolation in extended mode +fails:Regexps with interpolation allows escape sequences in interpolated regexps diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/regexp/modifiers_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/regexp/modifiers_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,9 @@ +fails:Regexps with modifers supports /m (multiline) +fails:Regexps with modifers supports /x (extended syntax) +fails:Regexps with modifers supports /o (once) +fails:Regexps with modifers invokes substitutions for /o only once +fails:Regexps with modifers supports (?imx-imx) (inline modifiers) +fails:Regexps with modifers supports (?imx-imx:expr) (scoped inline modifiers) +fails:Regexps with modifers supports . with /m +fails:Regexps with modifers supports ASII/Unicode modifiers +fails:Regexps with modifers raises SyntaxError for ASII/Unicode modifiers diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/regexp/repetition_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/regexp/repetition_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,1 @@ +fails:Regexps with repetition does not treat {m,n}+ as possessive diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/specs/tags/language/regexp_tags.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/specs/tags/language/regexp_tags.txt Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,16 @@ +fails:Literal Regexps matches against $_ (last input) in a conditional if no explicit matchee provided +fails:Literal Regexps throws SyntaxError for malformed literals +fails:Literal Regexps supports paired delimiters with %r +fails:Literal Regexps supports grouping constructs that are also paired delimiters +fails:Literal Regexps allows second part of paired delimiters to be used as non-paired delimiters +fails:Literal Regexps supports non-paired delimiters delimiters with %r +fails:Literal Regexps allows unescaped / to be used with %r +fails:Literal Regexps supports . (any character except line terminator) +fails:Literal Regexps supports | (alternations) +fails:Literal Regexps supports (?> ) (embedded subexpression) +fails:Literal Regexps supports (?# ) +fails:Literal Regexps supports (?<= ) (positive lookbehind) +fails:Literal Regexps supports (? 2 }; puts bar.to_s"); + } + + @Test + public void testInclude() { + assertPrints("true\nfalse\n", "foo = [1, 2, 3, 4]; puts foo.include? 2; puts foo.include? 5"); + } + + @Test + public void testSub() { + assertPrints("[1, 4]\n", "puts ([1, 2, 2, 3, 4] - [2, 3]).to_s"); + } + + @Test + public void testJoin() { + assertPrints("1.2.3\n", "puts [1, 2, 3].join('.')"); + } + + @Test + public void testShift() { + assertPrints("1\n2\n3\n", "a = [1, 2, 3]; while b = a.shift; puts b; end"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/BignumTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/BignumTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.core; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test the {@code Bignum} class. + */ +public class BignumTests extends RubyTests { + + @Test + public void testImmediate() { + assertPrints("123456789123456789\n", "puts 123456789123456789"); + assertPrints("574658776654483828\n", "puts 574658776654483828"); + } + + @Test + public void testAddImmediate() { + assertPrints("821572354901397406\n", "puts 123456789123456789+698115565777940617"); + assertPrints("7675735362615108\n", "puts 867676857675 + 7674867685757433"); + assertPrints("8792416214481\n", "puts 8785647643454 + (6768571027)"); + assertPrints("8089240320234\n", "puts (7132953783486) + ((956286536748))"); + } + + @Test + public void testSubImmediate() { + assertPrints("574658776654483828\n", "puts 698115565777940617-123456789123456789"); + assertPrints("7674000008899758\n", "puts 7674867685757433 - 867676857675"); + assertPrints("8778879072427\n", "puts 8785647643454 - (6768571027)"); + assertPrints("6176667246738\n", "puts (7132953783486) - ((956286536748))"); + } + + @Test + public void testLessImmediate() { + assertPrints("false\n", "puts 698115565777940617 < 123456789123456789"); + assertPrints("true\n", "puts 867676857675 < 7674867685757433"); + assertPrints("false\n", "puts 8785647643454 < (6768571027)"); + assertPrints("true\n", "puts (956286536748) < ((7132953783486))"); + } + + @Test + public void testDivmod() { + assertPrints("100\n2342\n", "puts 1000000000000000000000002342.divmod(10000000000000000000000000)"); + assertPrints("Fixnum\n", "puts 1000000000000000000000002342.divmod(10000000000000000000000000)[0].class"); + assertPrints("Fixnum\n", "puts 1000000000000000000000002342.divmod(10000000000000000000000000)[1].class"); + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/BoolTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/BoolTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.core; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test {@code true} and {@code false}. Note that there is no {@code Bool} class or type. There is + * {@code TrueClass}, {@code FalseClass}, and instances of them {@code true} and {@code false}. + */ +public class BoolTests extends RubyTests { + + @Test + public void testImmediate() { + assertPrints("true\n", "puts true"); + assertPrints("false\n", "puts false"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/ContinuationTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/ContinuationTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.core; + +import org.junit.*; + +import com.oracle.truffle.ruby.runtime.configuration.*; +import com.oracle.truffle.ruby.test.*; + +/** + * Test the {@code Continuation} class. + */ +public class ContinuationTests extends RubyTests { + + @Test + public void testRequired18() { + assertPrints(RubyVersion.RUBY_18, "", "callcc { |c| c.call }"); + } + + @Test + public void testRequired19() { + assertPrints(RubyVersion.RUBY_19, "", "require \"continuation\"; callcc { |c| c.call }"); + } + + @Test + public void testRequired20() { + assertPrints(RubyVersion.RUBY_20, "", "require \"continuation\"; callcc { |c| c.call }"); + } + + @Test + public void testOneShotGoingUpCallstack() { + assertPrints(RubyVersion.RUBY_18, "1\n3\n", "callcc { |c| puts 1; c.call; puts 2 }; puts 3"); + } + + @Test + public void testOneShotGoingUpCallstackReturnValue() { + assertPrints(RubyVersion.RUBY_18, "14\n", "puts callcc { |c| c.call 14 }"); + } + + @Test + public void testNestedOneShotGoingUpCallstack() { + assertPrints(RubyVersion.RUBY_18, "1\n2\n4\n5\n", "callcc { |c1| puts 1; callcc { |c2| puts 2; c2.call; puts 3 }; puts 4 }; puts 5"); + assertPrints(RubyVersion.RUBY_18, "1\n2\n5\n", "callcc { |c1| puts 1; callcc { |c2| puts 2; c1.call; puts 3 }; puts 4 }; puts 5"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/FiberTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/FiberTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.core; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test the {@code Fiber} class. + */ +public class FiberTests extends RubyTests { + + @Test + public void testResume() { + assertPrints("14\n", "f = Fiber.new { |x| puts x }; f.resume 14"); + } + + @Test + public void testYield() { + assertPrints("14\n", "f = Fiber.new { |x| Fiber.yield x }; puts f.resume(14)"); + } + + @Test + public void testCountdown() { + assertPrints("", "f = Fiber.new do |n|\n" + // + " loop do\n" + // + " n = Fiber.yield n - 1\n" + // + " end\n" + // + "end\n" + // + "\n" + // + "n = 1000\n" + // + "\n" + // + "while n > 0\n" + // + " n = f.resume n\n" + // + "end\n"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/FixnumTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/FixnumTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.core; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test the {@code Fixnum} class. + */ +public class FixnumTests extends RubyTests { + + @Test + public void testImmediate() { + assertPrints("2\n", "puts 2"); + assertPrints("14\n", "puts 14"); + assertPrints("-14\n", "puts -14"); + } + + @Test + public void testNegate() { + assertPrints("-1\n", "x = 1; puts -x"); + assertPrints("1\n", "x = -1; puts -x"); + } + + @Test + public void testAddImmediate() { + assertPrints("16\n", "puts 14+2"); + assertPrints("14\n", "puts 12 + 2"); + assertPrints("17\n", "puts 9 + (8)"); + assertPrints("10\n", "puts (6) + ((4))"); + } + + @Test + public void testSubImmediate() { + assertPrints("12\n", "puts 14-2"); + assertPrints("10\n", "puts 12 - 2"); + assertPrints("1\n", "puts 9 - (8)"); + assertPrints("2\n", "puts (6) - ((4))"); + } + + @Test + public void testMulImmediate() { + assertPrints("28\n", "puts 14 * 2"); + assertPrints("20\n", "puts 2 * 10"); + assertPrints("72\n", "puts 9 * (8)"); + assertPrints("24\n", "puts (4) * ((6))"); + } + + @Test + public void testDivImmediate() { + assertPrints("7\n", "puts 14 / 2"); + assertPrints("0\n", "puts 2 / 10"); + assertPrints("1\n", "puts 9 / (8)"); + assertPrints("0\n", "puts (4) / ((6))"); + } + + @Test + public void testEqualImmediate() { + assertPrints("true\n", "puts 14 == 14"); + assertPrints("true\n", "puts 2 == 2"); + assertPrints("false\n", "puts 9 == (8)"); + assertPrints("false\n", "puts (4) == ((6))"); + } + + @Test + public void testNotEqualImmediate() { + assertPrints("false\n", "puts 14 != 14"); + assertPrints("false\n", "puts 2 != 2"); + assertPrints("true\n", "puts 9 != (8)"); + assertPrints("true\n", "puts (4) != ((6))"); + } + + @Test + public void testLessImmediate() { + assertPrints("false\n", "puts 14 < 2"); + assertPrints("true\n", "puts 2 < 10"); + assertPrints("false\n", "puts 9 < (8)"); + assertPrints("true\n", "puts (4) < ((6))"); + } + + @Test + public void testGreaterEqualImmediate() { + assertPrints("true\n", "puts 14 >= 14"); + assertPrints("true\n", "puts 14 >= 2"); + assertPrints("false\n", "puts 2 >= 10"); + assertPrints("true\n", "puts 9 >= (8)"); + assertPrints("false\n", "puts (4) >= ((6))"); + } + + @Test + public void testLeftShift() { + assertPrints("0\n", "puts 0 << 0"); + assertPrints("0\n", "puts 0 << 1"); + assertPrints("1\n", "puts 1 << 0"); + assertPrints("0\n", "puts 1 << -1"); + assertPrints("0\n", "puts 1 << -2"); + assertPrints("28\n", "puts 14 << 1"); + assertPrints("7\n", "puts 14 << -1"); + assertPrints("4294967296\n", "puts 1 << 32"); + assertPrints("340282366920938463463374607431768211456\n", "puts 1 << 128"); + assertPrints("0\n", "puts 1 << -32"); + assertPrints("Fixnum\n", "puts (14 << 1).class"); + assertPrints("Bignum\n", "puts (1 << 32).class"); + } + + @Test + public void testDivmod() { + // @formatter:off + final int[][] tests = new int[][]{ + new int[]{13, 4, 3, 1}, + new int[]{13, -4, -4, -3}, + new int[]{-13, 4, -4, 3}, + new int[]{-13, -4, 3, -1}}; + // @formatter:on + + for (int[] test : tests) { + final int a = test[0]; + final int b = test[1]; + final int q = test[2]; + final int r = test[3]; + assertPrints(String.format("%d\n%d\n", q, r), String.format("puts %d.divmod(%d)", a, b)); + } + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/FloatTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/FloatTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.core; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test the {@code Float} class. + */ +public class FloatTests extends RubyTests { + + @Test + public void testImmediate() { + assertPrints("2.5\n", "puts 2.5"); + assertPrints("14.33\n", "puts 14.33"); + } + + @Test + public void testAddImmediate() { + assertPrints("16.2\n", "puts 14.1+2.1"); + assertPrints("14.2\n", "puts 12.1 + 2.1"); + assertPrints("17.2\n", "puts 9.1 + (8.1)"); + assertPrints("10.2\n", "puts (6.1) + ((4.1))"); + } + + @Test + public void testSubImmediate() { + assertPrints("12.1\n", "puts 14.2-2.1"); + assertPrints("10.1\n", "puts 12.2 - 2.1"); + assertPrints("1.0999999999999996\n", "puts 9.2 - (8.1)"); + assertPrints("2.1000000000000005\n", "puts (6.2) - ((4.1))"); + } + + @Test + public void testMulImmediate() { + assertPrints("29.82\n", "puts 14.2*2.1"); + assertPrints("25.62\n", "puts 12.2 * 2.1"); + assertPrints("74.52\n", "puts 9.2 * (8.1)"); + assertPrints("25.419999999999998\n", "puts (6.2) * ((4.1))"); + assertPrints("7.5\n", "puts 2.5 * 3"); + assertPrints("7.5\n", "puts 3 * 2.5"); + } + + @Test + public void testDivImmediate() { + assertPrints("6.761904761904761\n", "puts 14.2/2.1"); + assertPrints("5.809523809523809\n", "puts 12.2 / 2.1"); + assertPrints("1.1358024691358024\n", "puts 9.2 / (8.1)"); + assertPrints("1.5121951219512197\n", "puts (6.2) / ((4.1))"); + assertPrints("0.8333333333333334\n", "puts 2.5 / 3"); + assertPrints("1.2\n", "puts 3 / 2.5"); + } + + @Test + public void testLessImmediate() { + assertPrints("false\n", "puts 14.2<2.2"); + assertPrints("true\n", "puts 2.2 < 10.2"); + assertPrints("false\n", "puts 9.2 < (8.2)"); + assertPrints("true\n", "puts (4.2) < ((6.2))"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/HashTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/HashTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.core; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test the {@code Hash} class. + */ +public class HashTests extends RubyTests { + + @Test + public void testLiteral() { + assertPrints("Hash\n", "puts ({}).class"); + assertPrints("Hash\n", "puts ({1 => 2, 3 => 4}).class"); + assertPrints("Hash\n", "puts ({key1: 2, key3: 4}).class"); + } + + @Test + public void testIndex() { + assertPrints("4\n", "foo = {1 => 2, 3 => 4}; puts foo[3]"); + } + + @Test + public void testIndexSet() { + assertPrints("6\n", "foo = {1 => 2, 3 => 4}; foo[5] = 6; puts foo[5]"); + } + + @Test + public void testKeys() { + assertPrints("[1, 3]\n", "foo = {1 => 2, 3 => 4}; puts foo.keys.to_s"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/IntegerTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/IntegerTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.core; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test the {@code Integer} class. + */ +public class IntegerTests extends RubyTests { + + @Test + public void testTimes() { + assertPrints("0\n", "1.times { |i| puts i }"); + assertPrints("0\n1\n2\n", "3.times { |i| puts i }"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/KernelTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/KernelTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.core; + +import org.junit.*; + +import com.oracle.truffle.ruby.runtime.configuration.*; +import com.oracle.truffle.ruby.test.*; + +/** + * Test {@code Kernel}. + */ +public class KernelTests extends RubyTests { + + @Test + public void testPutsEmpty() { + assertPrints("\n", "puts"); + } + + @Test + public void testPutsString() { + assertPrints("1\n", "puts 1"); + } + + @Test + public void testPrintfNoFormatting() { + assertPrints("", "printf"); + assertPrints("foo", "printf \"foo\""); + assertPrints("foo\n", "printf \"foo\\n\""); + } + + @Test + public void testPrintfDecimal() { + assertPrints("foo14bar", "printf \"foo%dbar\", 14"); + } + + @Test + public void testGets() { + assertPrintsWithInput("test\n", "puts gets", "test\n"); + } + + @Test + public void testInteger() { + assertPrints("14\n", "puts Integer(\"14\")"); + } + + @Test + public void testEval() { + assertPrints("16\n", "puts eval(\"14 + 2\")"); + } + + @Test + public void testBindingLocalVariables() { + // Use the current binding for eval + assertPrints("16\n", "x = 14; y = 2; puts eval(\"x + y\", binding)"); + + // Use the binding returned from a method for eval + assertPrints("16\n", "def foo; x = 14; y = 2; binding; end; puts eval(\"x + y\", foo)"); + } + + @Test + public void testBindingInstanceVariables() { + // Use the binding returned from a method in an object for eval + assertPrints("16\n", "class Foo; def foo; @x = 14; @y = 2; binding; end; end; puts eval(\"@x + @y\", Foo.new.foo)"); + } + + @Test + public void testSetTraceFuncLine() { + final ConfigurationBuilder configuration = new ConfigurationBuilder(); + configuration.setTrace(true); + + final String code = "def foo\n" + // + " a = 14\n" + // + " b = 2\n" + // + " a + b\n" + // + "end\n" + // + "\n" + // + "set_trace_func proc { |event, file, line, id, binding, classname|\n" + // + " if event == \"line\"\n" + // + " puts file + \":\" + line.to_s\n" + // + " end\n" + // + "}\n" + // + "\n" + // + "foo"; + final String input = ""; + final String expected = "(test):13\n(test):2\n(test):3\n(test):4\n"; + assertPrints(new Configuration(configuration), expected, "(test)", code, input); + } + + @Test + public void testBlockGiven() { + assertPrints("false\n", "def foo; puts block_given?; end; foo"); + assertPrints("true\n", "def foo; puts block_given?; end; foo do; end"); + assertPrints("true\n", "def foo; puts block_given?; end; foo {}"); + assertPrints("true\n", "def foo; puts block_given?; end; foo &:+"); + } + + @Test + public void testLoop() { + assertPrints("14\n", "loop do; break; end; puts 14"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/MathTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/MathTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.core; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test the {@code Math} class. + */ +public class MathTests extends RubyTests { + + @Test + public void testPI() { + assertPrints("3.141592653589793\n", "puts Math::PI"); + } + + @Test + public void testSqrt() { + assertPrints("1.0\n", "puts Math.sqrt(1)"); + assertPrints("1.0\n", "puts Math::sqrt(1)"); + assertPrints("3.7416573867739413\n", "puts Math::sqrt(14)"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/ModuleTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/ModuleTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.core; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test the {@code Module} class. + */ +public class ModuleTests extends RubyTests { + + @Test + public void testAttrAccessor() { + assertPrints("14\n", "class Foo; attr_accessor :x end; foo=Foo.new; foo.x=14; puts foo.x"); + assertPrints("14\n", "class Foo; attr_accessor(:x) end; foo=Foo.new; foo.x=14; puts foo.x"); + assertPrints("16\n", "class Foo; attr_accessor(:x, :y) end; foo=Foo.new; foo.x=14; foo.y=2; puts foo.x + foo.y"); + assertPrints("16\n", "class Foo; attr_accessor :x end; foo=Foo.new; foo.x=2; foo.x+=14; puts foo.x"); + } + + @Test + public void testDefineMethod() { + /* + * We use Object#send instead of calling define_method directly because that method is + * private. + */ + + assertPrints("14\n", "class Foo; end; Foo.send(:define_method, :foo) do; puts 14; end; Foo.new.foo"); + } + + @Test + public void testDefinedBeforeScopeRun() { + assertPrints("Module\n", "module Foo; puts Foo.class; end"); + } + + @Test + public void testDefinedInRootScopeBeforeScopeRun() { + assertPrints("Module\n", "module Foo; puts ::Foo.class; end"); + } + + @Test + public void testModuleEval() { + assertPrints("14\n", "class Foo; puts 14; end; Foo.module_eval('def foo; end'); Foo.new.foo"); + } + + @Test + public void testNextInBlock() { + assertPrints("1\n1\n1\n", "3.times do; puts 1; next; puts 2; end"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/ObjectSpaceTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/ObjectSpaceTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.core; + +import org.junit.*; + +import com.oracle.truffle.ruby.runtime.configuration.*; +import com.oracle.truffle.ruby.test.*; + +/** + * Test the {@code ObjectSpace} module. + */ +public class ObjectSpaceTests extends RubyTests { + + @Test + public void testEachObjectClass() { + assertPrints("true\n", "found_string = false; ObjectSpace.each_object(Class) { |o| if o == String; found_string = true; end }; puts found_string"); + } + + @Test + public void testId2RefClass() { + assertPrints("true\n", "puts ObjectSpace._id2ref(String.object_id) == String"); + } + + @Test + public void testEachObjectString() { + final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.setFullObjectSpace(true); + final String code = "foo = \"foo\"; found_foo = false; ObjectSpace.each_object(String) { |o| if o == foo; found_foo= true; end }; puts found_foo"; + final String input = ""; + final String expected = "true\n"; + assertPrints(new Configuration(configurationBuilder), expected, "(test)", code, input); + } + + @Test + public void testId2RefString() { + final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.setFullObjectSpace(true); + final String code = "foo = \"foo\"; puts ObjectSpace._id2ref(foo.object_id) == foo"; + final String input = ""; + final String expected = "true\n"; + assertPrints(new Configuration(configurationBuilder), expected, "(test)", code, input); + } + + @Test + public void testGarbageCollect() { + assertPrints("", "ObjectSpace.garbage_collect"); + assertPrints("", "ObjectSpace.start"); + } +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/ObjectTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/ObjectTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.core; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test the {@code Object} class. + */ +public class ObjectTests extends RubyTests { + + @Test + public void testARGV() { + assertPrints("1\n2\n3\n", "puts ARGV", "1", "2", "3"); + } + + @Test + public void testInstanceVariableDefined() { + assertPrints("true\n", "class Foo; def initialize; @bar=14; end; end; puts Foo.new.instance_variable_defined?(:@bar)"); + assertPrints("true\n", "class Foo; def initialize; @bar=14; end; end; puts Foo.new.instance_variable_defined?(\"@bar\")"); + assertPrints("true\n", "class Foo; def initialize; instance_variable_set(:@bar, 14); end; end; puts Foo.new.instance_variable_defined?(\"@bar\")"); + assertPrints("false\n", "class Foo; def initialize; @foo=14; end; end; puts Foo.new.instance_variable_defined?(:@bar)"); + assertPrints("false\n", "class Foo; def initialize; @foo=14; end; end; puts Foo.new.instance_variable_defined?(\"@bar\")"); + assertPrints("false\n", "class Foo; def initialize; instance_variable_set(:@foo, 14); end; end; puts Foo.new.instance_variable_defined?(\"@bar\")"); + } + + @Test + public void testInstanceVariableGet() { + assertPrints("14\n", "class Foo; def initialize; @bar=14; end; end; puts Foo.new.instance_variable_get(:@bar)"); + assertPrints("14\n", "class Foo; def initialize; @bar=14; end; end; puts Foo.new.instance_variable_get(\"@bar\")"); + } + + @Test + public void testInstanceVariableSet() { + assertPrints("14\n", "class Foo; attr_accessor :bar; end; foo = Foo.new; foo.instance_variable_set(:@bar, 14); puts foo.bar"); + assertPrints("14\n", "class Foo; attr_accessor :bar; end; foo = Foo.new; foo.instance_variable_set(\"@bar\", 14); puts foo.bar"); + } + + @Test + public void testInstanceVariables() { + assertPrints("a\nb\n", "class Foo; def initialize; @a=2; @b=14; end; end; puts Foo.new.instance_variables"); + assertPrints("a\nb\n", "class Foo; def initialize; @a=2; instance_variable_set(:@b, 14); end; end; puts Foo.new.instance_variables"); + } + + @Test + public void testSend() { + assertPrints("14\n", "self.send(:puts, 14)"); + assertPrints("14\n", "self.send(\"puts\", 14)"); + } + + @Test + public void testExtend() { + assertPrints("14\n", "class Foo; end; module Bar; def bar; puts 14; end; end; foo = Foo.new; foo.extend(Bar); foo.bar"); + } + + @Test + public void testSingletonMethods() { + assertPrints("[:baz]\n", "class Foo; def bar; end; end; foo = Foo.new; def foo.baz; end; puts foo.singleton_methods.to_s"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/ProcTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/ProcTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.core; + +import org.junit.*; + +import com.oracle.truffle.ruby.runtime.configuration.*; +import com.oracle.truffle.ruby.test.*; + +/** + * Test the {@code Proc} class. + */ +public class ProcTests extends RubyTests { + + @Test + public void testKernelProc() { + assertPrints("1\n", "x = proc { puts 1 }; x.call"); + assertPrints("1\n", "x = proc { 1 }; puts x.call"); + } + + @Test + public void testKernelLambda() { + assertPrints("1\n", "x = lambda { puts 1 }; x.call"); + assertPrints("1\n", "x = lambda { 1 }; puts x.call"); + } + + @Test + public void testKernelProcNew() { + assertPrints("1\n", "x = Proc.new { puts 1 }; x.call"); + assertPrints("1\n", "x = Proc.new { 1 }; puts x.call"); + } + + @Test + public void testProcReturn18() { + assertPrints(RubyVersion.RUBY_18, "2\n", "def foo; x = proc { return 1 }; x.call; return 2; end; puts foo"); + } + + @Test + public void testProcReturn19() { + assertPrints(RubyVersion.RUBY_19, "1\n", "def foo; x = proc { return 1 }; x.call; return 2; end; puts foo"); + } + + @Test + public void testProcReturn20() { + assertPrints(RubyVersion.RUBY_20, "1\n", "def foo; x = proc { return 1 }; x.call; return 2; end; puts foo"); + } + + @Test + public void testLambdaReturn() { + assertPrints("2\n", "def foo; x = lambda { return 1 }; x.call; return 2; end; puts foo"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/RangeTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/RangeTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.core; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test the {@code Range} class. + */ +public class RangeTests extends RubyTests { + + @Test + public void testImmediate() { + assertPrints("1..2\n", "puts 1..2"); + assertPrints("1..2\n", "puts (1..2)"); + assertPrints("1..2\n", "puts ((1)..2)"); + assertPrints("1...2\n", "puts 1...2"); + } + + @Test + public void testVariables() { + assertPrints("1..2\n", "x = 1; puts x..2"); + assertPrints("1..2\n", "y = 2; puts 1..y"); + assertPrints("1..2\n", "x = 1; y = 2; puts x..y"); + } + + @Test + public void testToArray() { + assertPrints("0\n1\n2\n", "puts (0..2).to_a"); + assertPrints("1\n2\n", "puts (1..2).to_a"); + assertPrints("1\n2\n", "puts (1...3).to_a"); + assertPrints("1\n2\n3\n", "puts (1..3).to_a"); + } + + @Test + public void testEach() { + assertPrints("", "(1...1).each { |n| puts n }"); + assertPrints("1\n", "(1...2).each { |n| puts n }"); + assertPrints("1\n2\n", "(1...3).each { |n| puts n }"); + assertPrints("1\n2\n3\n", "(1...4).each { |n| puts n }"); + assertPrints("1\n", "(1..1).each { |n| puts n }"); + assertPrints("1\n2\n", "(1..2).each { |n| puts n }"); + assertPrints("1\n2\n3\n", "(1..3).each { |n| puts n }"); + assertPrints("1\n2\n3\n4\n", "(1..4).each { |n| puts n }"); + assertPrints("0\n1\n", "(0..1).each { |n| puts n }"); + assertPrints("", "(4..-2).each { |n| puts n }"); + assertPrints("-4\n-3\n-2\n", "(-4..-2).each { |n| puts n }"); + assertPrints("-1\n0\n1\n", "(-1..1).each { |n| puts n }"); + } + + @Test + public void testMap() { + assertPrints("2\n4\n6\n", "puts (1..3).map { |n| n*2 }"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/RegexpTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/RegexpTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.core; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test the {@code Regexp} class. + */ +public class RegexpTests extends RubyTests { + + @Test + public void testLiteral() { + assertPrints("Regexp\n", "puts /foo/.class"); + } + + @Test + public void testInterpolatedLiteral() { + assertPrints("Regexp\n", "puts /foo#{1}/.class"); + } + + @Test + public void testMatch() { + assertPrints("0\n", "puts(/foo/ =~ \"foo\")"); + assertPrints("0\n", "puts(\"foo\" =~ /foo/)"); + assertPrints("3\n", "puts(/foo/ =~ \"abcfoo\")"); + assertPrints("3\n", "puts(\"abcfoo\" =~ /foo/)"); + assertPrints("\n", "puts(/foo/ =~ \"abc\")"); + assertPrints("\n", "puts(\"abc\" =~ /foo/)"); + } + + @Test + public void testFrameLocalVariableResults() { + assertPrints("foo\nbar\nbaz\n", "/(foo)(bar)(baz)/ =~ 'foobarbaz'; puts $1; puts $2; puts $3"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/StringTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/StringTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.core; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test the {@code String} class. + */ +public class StringTests extends RubyTests { + + @Test + public void testToI() { + assertPrints("2\n", "puts \"2\".to_i"); + assertPrints("-2\n", "puts \"-2\".to_i"); + assertPrints("123456789123456789\n", "puts \"123456789123456789\".to_i"); + } + + @Test + public void testFormat() { + assertPrints("a\n", "puts \"a\""); + assertPrints("1\n", "puts \"%d\" % 1"); + assertPrints("a1b\n", "puts \"a%db\" % 1"); + assertPrints("a1.00000b\n", "puts \"a%fb\" % 1"); + assertPrints("a2.50000b\n", "puts \"a%fb\" % 2.5"); + assertPrints("3.400000000\n", "puts \"%.9f\" % 3.4"); + assertPrints("3.400000000\n", "puts \"%0.9f\" % 3.4"); + } + + @Test + public void testThreequal() { + assertPrints("false\n", "puts \"a\" === \"b\""); + assertPrints("true\n", "puts \"a\" === \"a\""); + } + + @Test + public void testIndex() { + assertPrints("a\n", "puts 'a'[0]"); + assertPrints("config\n", "puts 'foo.config'[-6..-1]"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/SymbolTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/SymbolTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.core; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test the {@code Symbol} class. + */ +public class SymbolTests extends RubyTests { + + @Test + public void testParses() { + assertPrints("", ":foo"); + assertPrints("", ":\"foo\""); + } + + @Test + public void testPuts() { + assertPrints("foo\n", "puts :foo"); + } + + @Test + public void testInterpolated() { + assertPrints("foo123\n", "puts :\"foo1#{2}3\""); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/ThreadTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/core/ThreadTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.core; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test the {@code Thread} class. + */ +public class ThreadTests extends RubyTests { + + @Test + public void testCreateJoin() { + assertPrints("1\n2\n", "t = Thread.new { puts 1 }; t.join; puts 2"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/debug/DebugTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/debug/DebugTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.debug; + +import org.junit.*; + +import com.oracle.truffle.ruby.runtime.configuration.*; +import com.oracle.truffle.ruby.test.*; + +/** + * Test the debugger. + */ +public class DebugTests extends RubyTests { + + @Test + public void testBreakContinue() { + final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.setDebug(true); + final Configuration configuration = new Configuration(configurationBuilder); + + final String fakeFileName = "test.rb"; + final String code = "Debug.break; puts 2"; + final String input = "puts 1 \n Debug.continue \n puts 'error' \n puts 'error'"; + final String expected = "1\n=> \n2\n"; + + assertPrints(configuration, expected, fakeFileName, code, input, new String[]{}); + } + + @Test + public void testLineBreak() { + final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.setDebug(true); + final Configuration configuration = new Configuration(configurationBuilder); + + final String fakeFileName = "test.rb"; + final String code = "Debug.break(\"test.rb\", 2) \n puts 2 \n puts 3"; + final String input = "puts 1 \n Debug.continue \n puts 'error' \n puts 'error'"; + final String expected = "1\n=> \n2\n3\n"; + + assertPrints(configuration, expected, fakeFileName, code, input, new String[]{}); + } + + @Test + public void testLineCustomBreak() { + final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.setDebug(true); + final Configuration configuration = new Configuration(configurationBuilder); + + final String fakeFileName = "test.rb"; + final String code = "Debug.break('test.rb', 2) { puts 1; Debug.break }\nputs 3\nputs 4"; + final String input = "puts 2 \n Debug.continue \n puts 'error' \n puts 'error'"; + final String expected = "1\n2\n=> \n3\n4\n"; + + assertPrints(configuration, expected, fakeFileName, code, input, new String[]{}); + } + + @Test + public void testLocalBreak() { + final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.setDebug(true); + final Configuration configuration = new Configuration(configurationBuilder); + + final String fakeFileName = "test.rb"; + final String code = "def foo \n puts 0 \n x = 14 \n end \n Debug.break(:foo, :x) \n foo \n puts 2"; + final String input = "puts 1 \n Debug.continue \n puts 'error' \n puts 'error'"; + final String expected = "0\n1\n=> \n2\n"; + + assertPrints(configuration, expected, fakeFileName, code, input, new String[]{}); + } + + @Test + public void testLocalCustomBreak() { + final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.setDebug(true); + final Configuration configuration = new Configuration(configurationBuilder); + + final String fakeFileName = "test.rb"; + final String code = "def foo \n puts 0 \n x = 14 \n end \n Debug.break(:foo, :x) { |v| puts v; Debug.break } \n foo \n puts 2"; + final String input = "puts 1 \n Debug.continue \n puts 'error' \n puts 'error'"; + final String expected = "0\n14\n1\n=> \n2\n"; + + assertPrints(configuration, expected, fakeFileName, code, input, new String[]{}); + } + + @Test + public void testRemoveLineBreak() { + final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.setDebug(true); + final Configuration configuration = new Configuration(configurationBuilder); + + final String fakeFileName = "test.rb"; + final String code = "Debug.break('test.rb', 3) \n Debug.remove('test.rb', 3) \n puts 2 \n puts 3"; + final String input = "puts 1 \n Debug.continue \n puts 'error' \n puts 'error'"; + final String expected = "2\n3\n"; + + assertPrints(configuration, expected, fakeFileName, code, input, new String[]{}); + } + + @Test + public void testRemoveLocalBreak() { + final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.setDebug(true); + final Configuration configuration = new Configuration(configurationBuilder); + + final String fakeFileName = "test.rb"; + final String code = "def foo \n puts 0 \n x = 14 \n end \n Debug.break(:foo, :x) \n foo \n Debug.remove(:foo, :x) \n foo \n puts 2"; + final String input = "puts 1 \n Debug.continue \n puts 'error' \n puts 'error'"; + final String expected = "0\n1\n=> \n0\n2\n"; + + assertPrints(configuration, expected, fakeFileName, code, input, new String[]{}); + } + + @Test + public void testWhere() { + final ConfigurationBuilder configurationBuilder = new ConfigurationBuilder(); + configurationBuilder.setDebug(true); + final Configuration configuration = new Configuration(configurationBuilder); + + final String fakeFileName = "test.rb"; + final String code = "puts 1 \n Debug.where \n puts 2"; + final String expected = "1\ntest.rb:2\n2\n"; + + assertPrints(configuration, expected, fakeFileName, code, "", new String[]{}); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/AndTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/AndTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test {@code and} expressions, which unusually for Ruby are not methods. This is because with + * Ruby's eager evaluation there would be no way to implement the short circuit semantics. + */ +public class AndTests extends RubyTests { + + @Test + public void testImmediate() { + assertPrints("false\n", "puts false && false"); + assertPrints("false\n", "puts true && false"); + assertPrints("false\n", "puts false && true"); + assertPrints("true\n", "puts true && true"); + assertPrints("false\n", "puts (false and false)"); + assertPrints("false\n", "puts (true and false)"); + assertPrints("false\n", "puts (false and true)"); + assertPrints("true\n", "puts (true and true)"); + } + + @Test + public void testShortCircuits() { + assertPrints("false\nfalse\nfalse\n", "x = y = false; puts (x = false) && (y = false); puts x, y"); + assertPrints("false\ntrue\nfalse\n", "x = y = false; puts (x = true) && (y = false); puts x, y"); + assertPrints("false\nfalse\nfalse\n", "x = y = false; puts (x = false) && (y = true); puts x, y"); + assertPrints("true\ntrue\ntrue\n", "x = y = false; puts (x = true) && (y = true); puts x, y"); + assertPrints("false\nfalse\nfalse\n", "x = y = false; puts ((x = false) and (y = false)); puts x, y"); + assertPrints("false\ntrue\nfalse\n", "x = y = false; puts ((x = true) and (y = false)); puts x, y"); + assertPrints("false\nfalse\nfalse\n", "x = y = false; puts ((x = false) and (y = true)); puts x, y"); + assertPrints("true\ntrue\ntrue\n", "x = y = false; puts ((x = true) and (y = true)); puts x, y"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/BlockTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/BlockTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test blocks. + */ +public class BlockTests extends RubyTests { + + @Test + public void testSimpleYield() { + assertPrints("1\n", "def foo; yield; end; foo { puts 1 };"); + assertPrints("1\n", "def foo; yield; end; foo do; puts 1; end;"); + } + + @Test + public void testYieldOneParameter() { + assertPrints("1\n", "def foo; yield 1; end; foo { |x| puts x };"); + assertPrints("1\n", "def foo; yield 1; end; foo do |x|; puts x; end;"); + } + + @Test + public void testYieldTwoParameters() { + assertPrints("1\n2\n", "def foo; yield 1, 2; end; foo { |x, y| puts x; puts y; };"); + assertPrints("1\n2\n", "def foo; yield 1, 2; end; foo do |x, y|; puts x; puts y; end;"); + } + + @Test + public void testSelfCapturedInBlock() { + assertPrints("main\n", "[1].each { |n| puts self.to_s }"); + } + + @Test + public void testBlockArgumentsDestructure() { + /* + * This really subtle. If you pass an array to a block with more than one parameters, it + * will be destructured. Any other type won't be destructured. There's no annotation to + * indicate that, like there would be with a method with the * operator. + */ + + assertPrints("1\n", "[1].each { |x| puts x.to_s }"); + assertPrints("[1, 2]\n", "[[1, 2]].each { |xy| puts xy.to_s }"); + assertPrints("1\n2\n", "[[1, 2]].each { |x, y| puts x, y }"); + } + + @Test + public void testBlocksHaveTheirOwnScopeForAssignment() { + assertPrints("\n", "1.times { x = 14 }; puts defined? x"); + assertPrints("\n", "1.times do; x = 14; end; puts defined? x"); + } + + @Test + public void testImplicitForBlocksDoNotHaveTheirOwnScopeForAssignment() { + assertPrints("local-variable\n", "for n in [1]; x = 14; end; puts defined? x"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/CaseTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/CaseTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test {@code case} expressions. + */ +public class CaseTests extends RubyTests { + + @Test + public void testSingle() { + assertPrints("1\n4\n", "case 'a'; when 'a'; puts 1; when 'b'; puts 2; else; puts 3; end; puts 4"); + assertPrints("2\n4\n", "case 'b'; when 'a'; puts 1; when 'b'; puts 2; else; puts 3; end; puts 4"); + assertPrints("3\n4\n", "case 'c'; when 'a'; puts 1; when 'b'; puts 2; else; puts 3; end; puts 4"); + } + + @Test + public void testMultiple() { + assertPrints("1\n4\n", "case 'a'; when 'a', 'b'; puts 1; when 'c'; puts 2; else; puts 3; end; puts 4"); + assertPrints("1\n4\n", "case 'b'; when 'a', 'b'; puts 1; when 'c'; puts 2; else; puts 3; end; puts 4"); + assertPrints("2\n4\n", "case 'c'; when 'a', 'b'; puts 1; when 'c'; puts 2; else; puts 3; end; puts 4"); + assertPrints("3\n4\n", "case 'd'; when 'a', 'b'; puts 1; when 'c'; puts 2; else; puts 3; end; puts 4"); + } + + @Test + public void testSimpleConditions() { + assertPrints("1\n", "case; when true; puts 1; when false; puts 2; end"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/ClassLocalTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/ClassLocalTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test @@ class variables. There is a lot of counter-intuitive behavior here - they aren't instance + * variables in class objects. The books describe them as being in a 'class hierarchy', rather than + * in a class. Also, the object they are defined it is not consistent - sometimes it is the class of + * self, sometimes it's just self. + */ +public class ClassLocalTests extends RubyTests { + + @Test + public void testBasic() { + assertPrints("14\n", "@@x = 14; puts @@x"); + } + + /* + * Test that they are defined for a hierarchy, not a class. + */ + + @Test + public void testHeirarchyNotClassVariable() { + assertPrints("2\n", "class Foo; @@value = 14; end; class Bar < Foo; @@value = 2; end; class Foo; puts @@value; end"); + } + + /* + * Test that they take the correct class at different times. In a method, they use the class of + * self. In a class definition they use that class, not the class of self, which is Class. + */ + + @Test + public void testCorrectClass() { + assertPrints("1\n", "class Foo; @@x = 1; def foo; puts @@x; end; end; Foo.new.foo"); + } + + @Test + public void testWithinSelfMethod() { + assertPrints("14\n", "class Foo; @@foo = 14; def self.foo; @@foo; end; end; puts Foo.foo"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/ClassTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/ClassTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test {@code class} expressions. + */ +public class ClassTests extends RubyTests { + + @Test + public void testDefine() { + assertPrints("Foo\n", "class Foo; end; puts Foo"); + } + + @Test + public void testMethods() { + assertPrints("14\n", "class Foo; def test; return 14; end; end; foo=Foo.new; puts foo.test"); + assertPrints("14\n", "class Foo; def test(x); return x; end; end; foo=Foo.new; puts foo.test(14)"); + } + + @Test + public void testDefineHasScope() { + assertPrints("14\n", "x=14; class Foo; x=0; end; puts x"); + assertPrints("14\n", "class Foo; x=14; puts x; end"); + } + + @Test + public void testInitialise() { + assertPrints("14\n", "class Foo; def initialize; puts 14; end; end; Foo.new"); + assertPrints("14\n", "class Foo; def initialize(x); puts x; end; end; Foo.new 14"); + assertPrints("14\n", "class Foo; def initialize(x); puts x; end; end; Foo.new(14)"); + } + + @Test + public void testInstanceVariables() { + assertPrints("14\n", "class Foo; def a; @x=14; end; def b; @x; end; end; foo=Foo.new; foo.a; puts foo.b"); + } + + @Test + public void testMissingVariables() { + assertPrints("NilClass\n", "class Foo; def a; @x; end; end; foo=Foo.new; puts foo.a.class"); + } + + @Test + public void testClassConstants() { + assertPrints("14\n", "class Foo; X=14; def foo; puts X; end; end; foo=Foo.new; foo.foo"); + } + + @Test + public void testReopeningSingletonClass() { + assertPrints("1\n", "foo = Object.new; class << foo; def bar; puts 1; end; end; foo.bar"); + } + + @Test + public void testInheritance() { + assertPrints("14\n", "class Foo; def foo; puts 14; end; end; class Bar < Foo; end; Bar.new.foo"); + } + + @Test + public void testSingletonInheritance() { + assertPrints("14\n", "class Foo; def self.foo; puts 14; end; end; class Bar < Foo; end; Bar.foo"); + } + + @Test + public void testNestedClass() { + assertPrints("14\n", "class Foo; class Bar; def bar; 14; end; end; def foo; Bar.new; end; end; puts Foo.new.foo.bar"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/ConstantTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/ConstantTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +public class ConstantTests extends RubyTests { + + @Test + public void testTopLevelConstants() { + assertPrints("14\n", "X=14; class Foo; def foo; puts X; end; end; f=Foo.new; f.foo"); + } + + @Test + public void testNestedConstants() { + assertPrints("", "module X; class A; end; class B; class C < A; end; end; end"); + } + + @Test + public void testSearchInParentModules() { + assertPrints("14\n", "module A; C = 14; module B; def self.test; puts C; end; end; end; A::B.test"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/ForTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/ForTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test {@code for} expressions. + */ +public class ForTests extends RubyTests { + + @Test + public void testArray() { + assertPrints("1\n2\n3\n", "for x in [1, 2, 3]; puts x; end"); + assertPrints("1\n2\n3\n", "y = [1, 2, 3]; for x in y; puts x; end"); + } + + @Test + public void testRange() { + assertPrints("1\n2\n3\n", "for x in 1..3; puts x; end"); + assertPrints("1\n2\n3\n", "y = 1..3; for x in y; puts x; end"); + assertPrints("1\n2\n", "for x in 1...3; puts x; end"); + } + + @Test + public void testScopeRO() { + assertPrints("14\n", "x=14; for n in [1]; puts x; end"); + } + + @Test + public void testScopeRW() { + assertPrints("14\n", "x=0; for n in [1]; x=x+14; puts x; end"); + } + + @Test + public void testNoNewScope() { + assertPrints("14\n", "for i in [1]; v = 14; end; puts v"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/GlobalVariableTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/GlobalVariableTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test global variables. + */ +public class GlobalVariableTests extends RubyTests { + + @Test + public void testMinimal() { + assertPrints("14\n", "$foo = 14; puts $foo"); + } + + @Test + public void testScope() { + assertPrints("14\n", "def foo; $bar = 14; end; foo; puts $bar"); + assertPrints("14\n", "$bar = 14; def foo; puts $bar; end; foo"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/IfTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/IfTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test {@code if} expressions. + */ +public class IfTests extends RubyTests { + + @Test + public void testImmediateIf() { + assertPrints("1\n", "if true; puts 1 end"); + assertPrints("", "if false; puts 1 end"); + } + + @Test + public void testImmediateTrailingIf() { + assertPrints("1\n", "puts 1 if true"); + assertPrints("", "puts 1 if false"); + } + + @Test + public void testImmediateIfElse() { + assertPrints("1\n", "if true; puts 1 else puts 2 end"); + assertPrints("2\n", "if false; puts 1 else puts 2 end"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/InterpolatedStringTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/InterpolatedStringTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test interpolated strings - that is string literals with #{...} sections in them. Within those + * you can have arbitrary Ruby expressions. + */ +public class InterpolatedStringTests extends RubyTests { + + @Test + public void testBasic() { + assertPrints("123\n", "puts \"1#{2}3\""); + } + + @Test + public void testMethodCall() { + assertPrints("123\n", "def foo; 2; end; puts \"1#{foo}3\""); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/LocalTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/LocalTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test local variables. + */ +public class LocalTests extends RubyTests { + + @Test + public void testAssignmentTopLevel() { + assertPrints("1\n", "x = 1; puts x"); + } + + @Test + public void testAssignmentWithinMethod() { + assertPrints("1\n", "def foo; x = 1; puts x; end; foo"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/MethodTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/MethodTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.runtime.control.*; +import com.oracle.truffle.ruby.test.*; + +/** + * Test method definitions and calls. + */ +public class MethodTests extends RubyTests { + + @Test + public void testDefineCallNoArguments() { + assertPrints("1\n", "def foo; puts 1; end; foo()"); + assertPrints("1\n", "def foo; puts 1; end; foo"); + } + + @Test + public void testDefineCallOnePreArgument() { + assertPrints("1\n", "def foo(a); puts a; end; foo(1)"); + assertPrints("1\n", "def foo(a); puts a; end; foo 1"); + } + + @Test + public void testDefineCallTwoPreArguments() { + assertPrints("1\n2\n", "def foo(a, b); puts a; puts b; end; foo(1, 2)"); + assertPrints("1\n2\n", "def foo(a, b); puts a; puts b; end; foo 1, 2"); + } + + @Test + public void testSingleReturn() { + assertPrints("1\n", "def foo; return 1; end; puts foo"); + assertPrints("1\n", "def foo(n); return n; end; puts foo(1)"); + } + + @Test + public void testImplicitReturn() { + assertPrints("1\n", "def foo; 1; end; puts foo"); + assertPrints("3\n", "def foo; 1+2; end; puts foo"); + assertPrints("14\n", "def foo; x=14; end; puts foo"); + } + + @Test + public void testNestedCall() { + assertPrints("1\n", "def foo(n); return n; end; def bar(n); return foo(n); end; puts bar(1)"); + assertPrints("1\n1\n1\n", "def foo(n); puts n; return n; end; def bar(n); puts n; return foo(n); end; puts bar(1)"); + assertPrints("1\n1\n", "def foo(a, b); puts a; puts b; end; def bar(n); foo(n, n); end; bar(1)"); + } + + @Test + public void testNestedOperatorCall() { + assertPrints("3\n", "def foo(a, b); puts a + b; end; foo(1, 2)"); + } + + /** + * Tests that arguments are evaluated before method dispatch takes place, by putting an action + * in one of the arguments that modifies the method that we should find in dispatch. + */ + @Test + public void testArgumentsExecutedBeforeDispatch() { + /* + * We have to use Object#send instead of calling define_method directly because that method + * is private. + */ + + assertPrints("12\n", "def foo\n" + // + " Fixnum.send(:define_method, :+) do |other|\n" + // + " self - other\n" + // + " end \n" + // + " 2\n" + // + "end\n" + // + "puts 14 + foo"); + } + + @Test(expected = RaiseException.class) + public void testTooFewArguments1() { + assertPrints("", "def foo(a); end; foo()"); + } + + @Test(expected = RaiseException.class) + public void testTooFewArguments2() { + assertPrints("", "def foo(a, b); end; foo(1)"); + } + + @Test(expected = RaiseException.class) + public void testTooFewArguments3() { + assertPrints("", "def foo(a, b, c); end; foo(1, 2)"); + } + + @Test(expected = RaiseException.class) + public void testTooManyArguments1() { + assertPrints("", "def foo(); end; foo(1)"); + } + + @Test(expected = RaiseException.class) + public void testTooManyArguments2() { + assertPrints("", "def foo(a); end; foo(1, 2)"); + } + + @Test(expected = RaiseException.class) + public void testTooManyArguments3() { + assertPrints("", "def foo(a, b); end; foo(1, 2, 3)"); + } + + @Test + public void testPolymophicMethod() { + assertPrints("A\nB\n", "class A\n" + // + " def foo\n" + // + " puts \"A\"\n" + // + " end\n" + // + "end\n" + // + "\n" + // + "class B\n" + // + " def foo\n" + // + " puts \"B\"\n" + // + " end\n" + // + "end\n" + // + "\n" + // + "def bar(x)\n" + // + " x.foo\n" + // + "end\n" + // + "\n" + // + "a = A.new\n" + // + "b = B.new\n" + // + "\n" + // + "bar(a)\n" + // + "bar(b)\n"); + } + + @Test + public void testOneDefaultValue() { + assertPrints("1\n2\n", "def foo(a=1); puts a; end; foo; foo(2)"); + } + + @Test + public void testTwoDefaultValues() { + assertPrints("1\n2\n3\n2\n3\n4\n", "def foo(a=1,b=2); puts a; puts b; end; foo; foo(3); foo(3, 4)"); + } + + @Test + public void testOneDefaultValueAfterNonDefault() { + assertPrints("2\n1\n2\n3\n", "def foo(a, b=1); puts a; puts b; end; foo(2); foo(2, 3)"); + } + + @Test + public void testOneDefaultValueBeforeNonDefault() { + assertPrints("1\n2\n2\n3\n", "def foo(a=1, b); puts a; puts b; end; foo(2); foo(2, 3)"); + } + + @Test + public void testBlockArgument() { + assertPrints("1\n2\n3\n", "def foo(&block); block.call(14); end; puts 1; foo { |n| puts 2 }; puts 3"); + } + + @Test + public void testBlockArgumentWithOthers() { + assertPrints("1\n2\n3\n4\n5\n", "def foo(a, b, &block); puts a; block.call(14); puts b; end; puts 1; foo(2, 4) { |n| puts 3 }; puts 5"); + } + + @Test + public void testBlockPass() { + assertPrints("1\n2\n3\n", "def bar; yield; end; def foo(&block); bar(&block); end; puts 1; foo { puts 2 }; puts 3"); + } + + @Test + public void testBlockPassWithOthers() { + assertPrints("1\n2\n3\n4\n5\n", "def bar(a, b); puts a; yield; puts b; end; def foo(a, b, &block); bar(a, b, &block); end; puts 1; foo(2, 4) { puts 3 }; puts 5"); + } + + @Test + public void testSplatWhole() { + assertPrints("1\n2\n3\n", "def foo(a, b, c); puts a; puts b; puts c; end; d = [1, 2, 3]; foo(*d)"); + } + + @Test + public void testSplatSome() { + assertPrints("1\n2\n3\n", "def foo(a, b, c); puts a; puts b; puts c; end; d = [2, 3]; foo(1, *d)"); + } + + @Test + public void testSplatParam() { + assertPrints("[1, 2, 3]\n", "def foo(*bar); puts bar.to_s; end; foo(1, 2, 3)"); + } + + @Test + public void testSplatParamWithOther() { + assertPrints("1\n[2]\n", "def foo(a, *b); puts a.to_s; puts b.to_s; end; foo(1, 2)"); + } + + @Test + public void testSplatParamWithBlockPass() { + assertPrints("[1, 2, 3]\n", "def foo(*bar, &block); block.call(bar); end; foo(1, 2, 3) { |x| puts x.to_s }"); + } + + @Test + public void testSingletonMethod() { + assertPrints("1\n", "foo = Object.new; def foo.bar; puts 1; end; foo.bar"); + } + + @Test + public void testAlias() { + assertPrints("1\n", "def foo; puts 1; end; alias bar foo; bar"); + assertPrints("1\n", "class Foo; def foo; puts 1; end; alias bar foo; end; Foo.new.bar"); + } + + @Test + public void testAliasMethod() { + assertPrints("1\n", "class Foo; def foo; puts 1; end; alias_method :bar, :foo; end; Foo.new.bar"); + } + + @Test + public void testSymbolAsBlock() { + assertPrints("6\n", "puts [1, 2, 3].inject(&:+)"); + } + + @Test + public void testSuper() { + assertPrints("1\n2\n3\n", "class Foo; def foo; puts 2; end; end; class Bar < Foo; def foo; puts 1; super; puts 3; end; end; Bar.new.foo"); + } + + @Test + public void testSuperWithArgs() { + assertPrints("1\n2\n3\n", "class Foo; def foo(n); puts n; end; end; class Bar < Foo; def foo(n); puts 1; super(n); puts 3; end; end; Bar.new.foo(2)"); + } + + @Test + public void testPushSplat() { + assertPrints("[1, 0, 4]\n", "a = [1, 2, 3, 4]; b = [1, 2]; a[*b] = 0; puts a.to_s"); + } + + @Test + public void testBlocksPassedIntoBlocks() { + assertPrints("14\n", "def foo; 1.times do; yield; end; end; foo do; puts 14; end"); + } + + @Test + public void testBlocksNotPassedIntoFullMethods() { + assertPrints("no block\n", "def foo(&block); if block; puts 'block'; else; puts 'no block'; end; end; def bar; foo; end; bar do; end"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/ModuleTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/ModuleTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test {@code module} expressions. + */ +public class ModuleTests extends RubyTests { + + @Test + public void testDefine() { + assertPrints("Foo\n", "module Foo; end; puts Foo"); + } + + @Test + public void testWithConstantDefinition() { + assertPrints("14\n", "module Foo; FOO=14; end; puts Foo::FOO"); + } + + @Test + public void testWithConstantDefinitionAndAccessInDeclaration() { + assertPrints("14\n", "module Foo; FOO=14; puts FOO; end"); + } + + @Test + public void testCanAccessObjectConstantsInModuleDefinition() { + assertPrints("", "class Foo; end; module Bar; foo = Foo.new; end"); + } + + @Test + public void testInclude() { + assertPrints("14\n", "module Foo; FOO=14; end; module Bar; include Foo; end; puts Bar::FOO"); + } + + @Test + public void testModuleFunction() { + assertPrints("1\n", "module Foo; def bar; puts 1; end; module_function :bar; end; Foo::bar"); + } + + @Test + public void testDistinctModule() { + assertPrints("true\n", "module A; module X; end; end; module B; module X; end; end; puts A::X.object_id != B::X.object_id"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/MultipleAssignmentTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/MultipleAssignmentTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test multiple assignment, which is sort of like pattern matching for arrays. The arrays can be + * implicit on the RHS. + */ +public class MultipleAssignmentTests extends RubyTests { + + @Test + public void testToLocal() { + assertPrints("1\n2\n", "x, y = [1, 2]; puts x, y"); + assertPrints("1\n2\n", "x, y = 1, 2; puts x, y"); + assertPrints("1\n2\n", "x = [1, 2]; y, z = x; puts y, z"); + } + + @Test + public void testToArrayIndex() { + assertPrints("1\n2\n", "x = []; x[0], x[1] = 1, 2; puts x"); + } + + @Test + public void testSwap() { + assertPrints("2\n1\n", "a = [1]; b = [2]; a[0], b[0] = b[0], a[0]; puts a, b"); + } + + @Test + public void testProducesArray() { + assertPrints("1\n2\n", "puts((a, b = 1, 2))"); + } + + @Test + public void testWithSplat() { + assertPrints("1\n[2, 3]\n", "a, *b = [1, 2, 3]; puts a; puts b.to_s"); + } + + @Test + public void testWithSplatEmpty() { + assertPrints("1\n[]\n", "a, *b = [1]; puts a.to_s; puts b.to_s"); + } + + @Test + public void testWithSingleValueRHS() { + assertPrints("14\n\n\n", "a, b, c = 14; puts a; puts b; puts c"); + assertPrints("\n\n\n", "a, b, c = nil; puts a; puts b; puts c"); + } + + @Test + public void testWithSingleSplatLHSAndSingleValueRHS() { + assertPrints("[14]\n", "a = *14; puts a.to_s"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/OrTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/OrTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test {@code or} expressions, which unusually for Ruby are not methods. This is because with + * Ruby's eager evaluation there would be no way to implement the short circuit semantics. + */ +public class OrTests extends RubyTests { + + @Test + public void testImmediate() { + assertPrints("false\n", "puts false || false"); + assertPrints("true\n", "puts true || false"); + assertPrints("true\n", "puts false || true"); + assertPrints("true\n", "puts true || true"); + assertPrints("false\n", "puts (false or false)"); + assertPrints("true\n", "puts (true or false)"); + assertPrints("true\n", "puts (false or true)"); + assertPrints("true\n", "puts (true or true)"); + } + + @Test + public void testShortCircuits() { + assertPrints("false\nfalse\nfalse\n", "x = y = false; puts (x = false) || (y = false); puts x, y"); + assertPrints("true\ntrue\nfalse\n", "x = y = false; puts (x = true) || (y = false); puts x, y"); + assertPrints("true\nfalse\ntrue\n", "x = y = false; puts (x = false) || (y = true); puts x, y"); + assertPrints("true\ntrue\nfalse\n", "x = y = false; puts (x = true) || (y = true); puts x, y"); + assertPrints("false\nfalse\nfalse\n", "x = y = false; puts ((x = false) or (y = false)); puts x, y"); + assertPrints("true\ntrue\nfalse\n", "x = y = false; puts ((x = true) or (y = false)); puts x, y"); + assertPrints("true\nfalse\ntrue\n", "x = y = false; puts ((x = false) or (y = true)); puts x, y"); + assertPrints("true\ntrue\nfalse\n", "x = y = false; puts ((x = true) or (y = true)); puts x, y"); + } + + @Test + public void testOrAssign() { + assertPrints("true\n", "def foo; puts 1; false; end; x = true; x ||= foo; puts x"); + assertPrints("1\nfalse\n", "def foo; puts 1; false; end; x = false; x ||= foo; puts x"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/PolymorphismTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/PolymorphismTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test characteristics of polymorphism. + */ +public class PolymorphismTests extends RubyTests { + + /** + * Test that a polymorphic method that will specialize to double will then not treat integers as + * doubles. + */ + @Test + public void testSimpleOperatorRedefinition() { + assertPrints("16.759999999999998\n16\n", // + "def add(x, y)\n" + // + " x + y\n" + // + "end\n" + // + "puts add(14.5, 2.26)\n" + // + "puts add(14, 2)\n"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/RaiseRescueTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/RaiseRescueTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.runtime.control.*; +import com.oracle.truffle.ruby.test.*; + +/** + * Test {@code raise} and {@code rescue}. + */ +public class RaiseRescueTests extends RubyTests { + + @Test(expected = RaiseException.class) + public void testZeroDivisionError() { + assertPrints("", "1/0"); + } + + @Test + public void testBeginRescue() { + assertPrints("", "begin; rescue; end"); + assertPrints("", "begin; rescue => e; end"); + assertPrints("", "begin; rescue ZeroDivisionError => e; end"); + assertPrints("", "begin; rescue; ensure; end"); + assertPrints("", "begin; rescue => e; ensure; end"); + assertPrints("", "begin; rescue ZeroDivisionError => e; ensure; end"); + assertPrints("", "begin; rescue; else; end"); + assertPrints("", "begin; rescue => e; else; end"); + assertPrints("", "begin; rescue ZeroDivisionError => e; else; end"); + assertPrints("", "def foo; rescue; end"); + assertPrints("", "def foo; rescue => e; end"); + assertPrints("", "def foo; rescue ZeroDivisionError => e; end"); + assertPrints("", "def foo; rescue; ensure; end"); + assertPrints("", "def foo; rescue => e; ensure; end"); + assertPrints("", "def foo; rescue ZeroDivisionError => e; ensure; end"); + assertPrints("", "def foo; rescue; else; end"); + assertPrints("", "def foo; rescue => e; else; end"); + assertPrints("", "def foo; rescue ZeroDivisionError => e; else; end"); + } + + @Test + public void testRescueZeroDivisionError() { + assertPrints("divided by 0\n3\n4\n", "begin; 1/0; puts 1; rescue => e; puts e; else puts 2; ensure puts 3; end; puts 4"); + assertPrints("divided by 0\n3\n4\n", "begin; 1/0; puts 1; rescue ZeroDivisionError => e; puts e; else puts 2; ensure puts 3; end; puts 4"); + assertPrints("1\n2\n3\n4\n", "begin; 1/1; puts 1; rescue ZeroDivisionError => e; puts e; else puts 2; ensure puts 3; end; puts 4"); + assertPrints("1\n2\n3\n4\n", "begin; 1/1; puts 1; rescue ZeroDivisionError => e; puts e; rescue NameError => e; puts e; else puts 2; ensure puts 3; end; puts 4"); + } + + @Test + public void testSplatRescue() { + assertPrints("2\n", "ERRORS=[ZeroDivisionError]; begin; 1/0; puts 1; rescue *ERRORS; puts 2; end"); + } + + @Test + public void testRetry() { + assertPrints("1\n3\n1\n2\n5\n", "x=0; begin; puts 1; 1/x; puts 2; rescue ZeroDivisionError; puts 3; x=1; retry; puts 4; end; puts 5"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/RedefinitionTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/RedefinitionTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test that methods can be redefined. + */ +public class RedefinitionTests extends RubyTests { + + /** + * Test that a method on Fixnum can be redefined and that we will use the new definition. The + * call that expects to find the redefinition needs to have already been specialized, which is + * why do it through a method. + */ + @Test + public void testSimpleOperatorRedefinition() { + assertPrints("3\n-1\n", // + "def add(x, y)\n" + // + " x + y\n" + // + "end\n" + // + "puts add(1, 2)\n" + // + "class Fixnum\n" + // + " def +(other)\n" + // + " self - other\n" + // + " end\n" + // + "end\n" + // + "puts add(1, 2)\n"); + } + + /** + * This is quite a subtle test. We redefine Float#+. We have a method which calls +. It is + * initially specialized to Fixnum, but then used with Float. The tricky bit is that Float has + * not been redefined since the operator has been specialized. The operator thinks it is up to + * date. When we emit a + node, we need to check if any class that that node could specialize to + * has been redefined. + */ + @Test + public void testSpecialisationConsidersRedefinitionInOtherClasses() { + assertPrints("16\n12.25\n", // + "def add(a, b)\n" + // + " a + b\n" + // + "end\n" + // + "class Float\n" + // + " def +(other)\n" + // + " self - other\n" + // + " end\n" + // + "end\n" + // + "puts add(14, 2)\n" + // + "puts add(14.5, 2.25)"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/ShortcutTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/ShortcutTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test shortcut expressions (syntactic sugar) such as {@code +=} and {@code |=}. + */ +public class ShortcutTests extends RubyTests { + + @Test + public void testShortcutAddAssign() { + assertPrints("2\n", "x = 1; x += 1; puts x"); + } + + @Test + public void testShortcutSubAssign() { + assertPrints("0\n", "x = 1; x -= 1; puts x"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/SpecialVariableTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/SpecialVariableTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test variables with special semantics, such as the 'global variables', {@code $_}, {@code $~} + * etc. + */ +public class SpecialVariableTests extends RubyTests { + + @Test + public void testGetsResult() { + assertPrintsWithInput("test\n", "gets; puts $_", "test\n"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/UntilTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/UntilTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test {@code until} expressions. + */ +public class UntilTests extends RubyTests { + + @Test + public void testSimpleWhile() { + assertPrints("0\n", "x = 10; until x == 0; x -= 1; end; puts x"); + assertPrints("10\n", "x = 0; until x == 10; x += 1; end; puts x"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/WhileTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/language/WhileTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.language; + +import org.junit.*; + +import com.oracle.truffle.ruby.test.*; + +/** + * Test {@code while} expressions. + */ +public class WhileTests extends RubyTests { + + @Test + public void testSimpleWhile() { + assertPrints("0\n", "x = 10; while x > 0; x -= 1; end; puts x"); + assertPrints("10\n", "x = 0; while x < 10; x += 1; end; puts x"); + } + + @Test + public void testBreak() { + assertPrints("1\n", "x = 0; while x < 10; x += 1; break; end; puts x"); + } + + @Test + public void testNext() { + assertPrints("10\n", "x = 0; while x < 10; x += 1; next; end; puts x"); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/runtime/ObjectLayoutTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.ruby.test/src/com/oracle/truffle/ruby/test/runtime/ObjectLayoutTests.java Mon Jan 06 14:30:23 2014 -0800 @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This + * code is released under a tri EPL/GPL/LGPL license. You can use it, + * redistribute it and/or modify it under the terms of the: + * + * Eclipse Public License version 1.0 + * GNU General Public License version 2 + * GNU Lesser General Public License version 2.1 + */ +package com.oracle.truffle.ruby.test.runtime; + +import org.junit.*; + +import com.oracle.truffle.ruby.runtime.*; +import com.oracle.truffle.ruby.runtime.core.*; +import com.oracle.truffle.ruby.runtime.objects.*; + +import static org.junit.Assert.*; + +/** + * Test the object layout classes. + */ +public class ObjectLayoutTests { + + @Test + public void testNewInstanceVariable() { + final RubyContext context = new RubyContext(null); + + // Create a class and an instance + + final RubyClass classA = new RubyClass(context, null, null, null, "A"); + final ObjectLayout layoutClassA = classA.getObjectLayoutForInstances(); + + final RubyBasicObject objectA = new RubyBasicObject(classA); + final ObjectLayout layoutObjectA = objectA.getObjectLayout(); + + // Add an instance variable to the instance + + objectA.setInstanceVariable("foo", 14); + + // That should have changed the layout of the class + + assertNotSame(layoutClassA, classA.getObjectLayoutForInstances()); + + // If we notify the object, it should also change the layout of that + + objectA.updateLayout(); + assertNotSame(layoutObjectA, objectA.getObjectLayout()); + + // We should be able to find that instance variable as a storage location in the class + + assertNotNull(classA.getObjectLayoutForInstances().findStorageLocation("foo")); + + // We should be able to read that value back out + + assertEquals(14, objectA.getInstanceVariable("foo")); + } + + @Test + public void testOverflowPrimitives() { + final RubyContext context = new RubyContext(null); + + // Create a class and an instance + + final RubyClass classA = new RubyClass(context, null, null, null, "A"); + final RubyBasicObject objectA = new RubyBasicObject(classA); + + // Add many more Fixnums that we have space for primitives + + final int count = 100; + + for (int n = 0; n < count; n++) { + objectA.setInstanceVariable("foo" + n, n); + } + + // We should be able to read them back out + + for (int n = 0; n < count; n++) { + assertEquals(n, objectA.getInstanceVariable("foo" + n)); + } + } + + @Test + public void testGeneralisation() { + final RubyContext context = new RubyContext(null); + + // Create a class and two instances + + final RubyClass classA = new RubyClass(context, null, null, null, "A"); + final RubyBasicObject object1 = new RubyBasicObject(classA); + final RubyBasicObject object2 = new RubyBasicObject(classA); + + // Set an instance variable to be a Fixnum in object 1 + + object1.setInstanceVariable("foo", 14); + + // We should be able to read that instance variable back, and it should still be a Fixnum + + assertEquals(14, object1.getInstanceVariable("foo")); + assertSame(Integer.class, object1.getInstanceVariable("foo").getClass()); + + // The underlying instance store should be Fixnum + + assertSame(FixnumStorageLocation.class, object1.getObjectLayout().findStorageLocation("foo").getClass()); + + /* + * The same instance variable in object 2 should be Nil. Note that this requires that we + * realise that even though the instance variable is known about in the layout of object 2, + * and we are using a primitive int to hold it, that it hasn't been set and is actually Nil. + * We don't want it to appear as 0. + */ + + assertSame(NilPlaceholder.INSTANCE, object2.getInstanceVariable("foo")); + + /* + * We should be able to set the same instance variable in object 2 to also be a Fixnum + * without changing the layout. + */ + + final ObjectLayout objectLayout2 = object2.getObjectLayout(); + object2.setInstanceVariable("foo", 2); + assertEquals(2, object2.getInstanceVariable("foo")); + assertSame(Integer.class, object2.getInstanceVariable("foo").getClass()); + assertSame(objectLayout2, object2.getObjectLayout()); + + // Set the instance variable in object 2 to be a Float + + object2.setInstanceVariable("foo", 2.25); + + // We should be able to read that instance variable back, and it should still be a Fixnum + + assertEquals(2.25, object2.getInstanceVariable("foo")); + assertSame(Double.class, object2.getInstanceVariable("foo").getClass()); + + // Object 1 should give still think the instance variable is a Fixnum + + assertEquals(14, object1.getInstanceVariable("foo")); + assertSame(Integer.class, object1.getInstanceVariable("foo").getClass()); + + // The underlying instance store in both objects should now be Object + + assertSame(ObjectStorageLocation.class, object1.getObjectLayout().findStorageLocation("foo").getClass()); + assertSame(ObjectStorageLocation.class, object2.getObjectLayout().findStorageLocation("foo").getClass()); + + } + + @Test + public void testSubclasses() { + final RubyContext context = new RubyContext(null); + + // Create two classes, A, and a subclass, B, and an instance of each + + final RubyClass classA = new RubyClass(context, null, null, null, "A"); + final RubyClass classB = new RubyClass(context, null, null, classA, "B"); + + ObjectLayout layoutClassA = classA.getObjectLayoutForInstances(); + ObjectLayout layoutClassB = classA.getObjectLayoutForInstances(); + + final RubyBasicObject objectA = new RubyBasicObject(classA); + final RubyBasicObject objectB = new RubyBasicObject(classB); + + ObjectLayout layoutObjectA = objectA.getObjectLayout(); + ObjectLayout layoutObjectB = objectB.getObjectLayout(); + + // Add an instance variable to the instance of A + + objectA.setInstanceVariable("foo", 14); + + // That should have changed the layout of both classes + + assertNotSame(layoutClassA, classA.getObjectLayoutForInstances()); + assertNotSame(layoutClassB, classB.getObjectLayoutForInstances()); + + layoutClassA = classA.getObjectLayoutForInstances(); + layoutClassB = classA.getObjectLayoutForInstances(); + + // If we notify the objects, both of them should have changed layouts + + objectA.updateLayout(); + objectB.updateLayout(); + assertNotSame(layoutObjectA, objectA.getObjectLayout()); + assertNotSame(layoutObjectB, objectB.getObjectLayout()); + + layoutObjectA = objectA.getObjectLayout(); + layoutObjectB = objectB.getObjectLayout(); + + // We should be able to find that instance variable as a storage location in both classes + + assertNotNull(classA.getObjectLayoutForInstances().findStorageLocation("foo")); + assertNotNull(classB.getObjectLayoutForInstances().findStorageLocation("foo")); + + // We should be able to read that value back out + + assertEquals(14, objectA.getInstanceVariable("foo")); + + // Add an instance variable to the instance of B + + objectB.setInstanceVariable("bar", 2); + + // This should not have changed the layout of A or the instance of A + + assertSame(layoutClassA, classA.getObjectLayoutForInstances()); + assertSame(layoutObjectA, objectA.getObjectLayout()); + + // But the layout of B and the instance of B should have changed + + assertNotSame(layoutClassB, classB.getObjectLayoutForInstances()); + + objectB.updateLayout(); + assertNotSame(layoutObjectB, objectB.getObjectLayout()); + + // We should be able to find the new instance variable in the instance of B but not A + + assertNull(classA.getObjectLayoutForInstances().findStorageLocation("bar")); + assertNotNull(classB.getObjectLayoutForInstances().findStorageLocation("bar")); + + // We should be able to read that value back out + + assertEquals(2, objectB.getInstanceVariable("bar")); + } + + @Test + public void testPerObjectInstanceVariables() { + final RubyContext context = new RubyContext(null); + + // Create a class and an instance + + final RubyClass classA = new RubyClass(context, context.getCoreLibrary().getClassClass(), null, null, "A"); + final RubyBasicObject objectA = new RubyBasicObject(classA); + + ObjectLayout layoutClassA = classA.getObjectLayoutForInstances(); + ObjectLayout layoutObjectA = objectA.getObjectLayout(); + + // Add an instance variable to the instance of A + + objectA.setInstanceVariable("foo", 2); + + // That should have changed the layout of the class and the object + + assertNotSame(layoutClassA, classA.getObjectLayoutForInstances()); + assertNotSame(layoutObjectA, objectA.getObjectLayout()); + layoutClassA = classA.getObjectLayoutForInstances(); + layoutObjectA = classA.getObjectLayout(); + + // We should be able to read the value back out + + assertEquals(2, objectA.getInstanceVariable("foo")); + + /* + * Switch object A to having a private object layout, as would be done by calls such as + * instance_variable_set. + */ + + objectA.switchToPrivateLayout(); + + // Set an instance variable on object A + + objectA.setInstanceVariable("bar", 14); + + // The layout of object A, however, should have changed + + // CS: it hasn't changed because it's still null + // assertNotSame(layoutObjectA, objectA.getObjectLayout()); + + // We should be able to read the value back out + + assertEquals(14, objectA.getInstanceVariable("bar")); + + /* + * We should also be able to read the first variable back out, even though we've switched to + * private layout since then. + */ + + assertEquals(2, objectA.getInstanceVariable("foo")); + } + +} diff -r 622af5fb8c58 -r 1ceb90be7bac mx/mx_graal.py --- a/mx/mx_graal.py Fri Jan 03 16:38:57 2014 -0800 +++ b/mx/mx_graal.py Mon Jan 06 14:30:23 2014 -0800 @@ -26,9 +26,10 @@ # # ---------------------------------------------------------------------------------------------------- -import os, sys, shutil, zipfile, tempfile, re, time, datetime, platform, subprocess, multiprocessing +import os, sys, shutil, zipfile, tempfile, re, time, datetime, platform, subprocess, multiprocessing, StringIO from os.path import join, exists, dirname, basename, getmtime from argparse import ArgumentParser, REMAINDER +from outputparser import OutputParser, ValuesMatcher import mx import xml.dom.minidom import sanitycheck @@ -1127,14 +1128,6 @@ dacapo(['100', 'eclipse', '-esa']) -def gv(args): - """run the Graal Visualizer""" - with open(join(_graal_home, '.graal_visualizer.log'), 'w') as fp: - mx.logv('[Graal Visualizer log is in ' + fp.name + ']') - if not exists(join(_graal_home, 'visualizer', 'build.xml')): - mx.logv('[This initial execution may take a while as the NetBeans platform needs to be downloaded]') - mx.run(['ant', '-f', join(_graal_home, 'visualizer', 'build.xml'), '-l', fp.name, 'run']) - def igv(args): """run the Ideal Graph Visualizer""" with open(join(_graal_home, '.ideal_graph_visualizer.log'), 'w') as fp: @@ -1370,6 +1363,17 @@ def isGraalEnabled(vm): return vm != 'original' and not vm.endswith('nograal') +def rubyShellCp(): + return mx.classpath("com.oracle.truffle.ruby.shell") + +def rubyShellClass(): + return "com.oracle.truffle.ruby.shell.Shell" + +def ruby(args): + """run a Ruby program or shell""" + vmArgs, rubyArgs = _extract_VM_args(args, useDoubleDash=True) + vm(vmArgs + ['-cp', rubyShellCp(), rubyShellClass()] + rubyArgs) + def site(args): """create a website containing javadoc and the project dependency graph""" @@ -1383,12 +1387,129 @@ '--title', 'Graal OpenJDK Project Documentation', '--dot-output-base', 'projects'] + args) +def generateZshCompletion(args): + """generate zsh completion for mx""" + try: + from genzshcomp import CompletionGenerator + except ImportError: + mx.abort("install genzshcomp (pip install genzshcomp)") + + # need to fake module for the custom mx arg parser, otherwise a check in genzshcomp fails + originalModule = mx._argParser.__module__ + mx._argParser.__module__ = "argparse" + generator = CompletionGenerator("mx", mx._argParser) + mx._argParser.__module__ = originalModule + + # strip last line and define local variable "ret" + complt = "\n".join(generator.get().split('\n')[0:-1]).replace('context state line', 'context state line ret=1') + + # add array of possible subcommands (as they are not part of the argument parser) + complt += '\n ": :->command" \\\n' + complt += ' "*::args:->args" && ret=0\n' + complt += '\n' + complt += 'case $state in\n' + complt += '\t(command)\n' + complt += '\t\tlocal -a main_commands\n' + complt += '\t\tmain_commands=(\n' + for cmd in sorted(mx._commands.iterkeys()): + c, _ = mx._commands[cmd][:2] + doc = c.__doc__ + complt += '\t\t\t"{0}'.format(cmd) + if doc: + complt += ':{0}'.format(_fixQuotes(doc.split('\n', 1)[0])) + complt += '"\n' + complt += '\t\t)\n' + complt += '\t\t_describe -t main_commands command main_commands && ret=0\n' + complt += '\t\t;;\n' + + complt += '\t(args)\n' + # TODO: improve matcher: if mx args are given, this doesn't work + complt += '\t\tcase $line[1] in\n' + complt += '\t\t\t(vm)\n' + complt += '\t\t\t\tnoglob \\\n' + complt += '\t\t\t\t\t_arguments -s -S \\\n' + complt += _appendOptions("graal", r"G\:") + # TODO: fix -XX:{-,+}Use* flags + complt += _appendOptions("hotspot", r"XX\:") + complt += '\t\t\t\t\t"-version" && ret=0 \n' + complt += '\t\t\t\t;;\n' + complt += '\t\tesac\n' + complt += '\t\t;;\n' + complt += 'esac\n' + complt += '\n' + complt += 'return $ret' + print complt + +def _fixQuotes(arg): + return arg.replace('\"', '').replace('\'', '').replace('`', '').replace('{', '\\{').replace('}', '\\}').replace('[', '\\[').replace(']', '\\]') + +def _appendOptions(optionType, optionPrefix): + def isBoolean(vmap, field): + return vmap[field] == "Boolean" or vmap[field] == "bool" + + def hasDescription(vmap): + return vmap['optDefault'] or vmap['optDoc'] + + complt = "" + for vmap in _parseVMOptions(optionType): + complt += '\t\t\t\t\t-"' + complt += optionPrefix + if isBoolean(vmap, 'optType'): + complt += '"{-,+}"' + complt += vmap['optName'] + if not isBoolean(vmap, 'optType'): + complt += '=' + if hasDescription(vmap): + complt += "[" + if vmap['optDefault']: + complt += r"(default\: " + vmap['optDefault'] + ")" + if vmap['optDoc']: + complt += _fixQuotes(vmap['optDoc']) + if hasDescription(vmap): + complt += "]" + complt += '" \\\n' + return complt + +def _parseVMOptions(optionType): + parser = OutputParser() + # TODO: the optDoc part can wrapped accross multiple lines, currently only the first line will be captured + # TODO: fix matching for float literals + jvmOptions = re.compile( + r"^[ \t]*" + r"(?P(Boolean|Integer|Float|Double|String|bool|intx|uintx|ccstr|double)) " + r"(?P[a-zA-Z0-9]+)" + r"[ \t]+=[ \t]*" + r"(?P([\-0-9]+(\.[0-9]+(\.[0-9]+\.[0-9]+))?|false|true|null|Name|sun\.boot\.class\.path))?" + r"[ \t]*" + r"(?P.+)?", + re.MULTILINE) + parser.addMatcher(ValuesMatcher(jvmOptions, { + 'optType' : '', + 'optName' : '', + 'optDefault' : '', + 'optDoc' : '', + })) + + # gather graal options + output = StringIO.StringIO() + vm(['-XX:-BootstrapGraal', '-G:+PrintFlags' if optionType == "graal" else '-XX:+PrintFlagsWithComments'], + vm = "graal", + vmbuild = "optimized", + nonZeroIsFatal = False, + out = output.write, + err = subprocess.STDOUT) + + valueMap = parser.parse(output.getvalue()) + return valueMap + + def mx_init(suite): commands = { 'build': [build, ''], 'buildvars': [buildvars, ''], 'buildvms': [buildvms, '[-options]'], 'clean': [clean, ''], + 'generateZshCompletion' : [generateZshCompletion, ''], 'hsdis': [hsdis, '[att]'], 'hcfdis': [hcfdis, ''], 'igv' : [igv, ''], @@ -1399,7 +1520,6 @@ 'specjbb2013': [specjbb2013, '[VM options] [-- [SPECjbb2013 options]]'], 'specjbb2005': [specjbb2005, '[VM options] [-- [SPECjbb2005 options]]'], 'gate' : [gate, '[-options]'], - 'gv' : [gv, ''], 'bench' : [bench, '[-resultfile file] [all(default)|dacapo|specjvm2008|bootstrap]'], 'unittest' : [unittest, '[VM options] [filters...]', _unittestHelpSuffix], 'longunittest' : [longunittest, '[VM options] [filters...]', _unittestHelpSuffix], @@ -1413,6 +1533,7 @@ 'longtests' : [longtests, ''], 'sl' : [sl, '[SL args|@VM options]'], 'trufflejar' : [trufflejar, ''], + 'ruby' : [ruby, '[Ruby args|@VM options]'] } mx.add_argument('--jacoco', help='instruments com.oracle.* classes using JaCoCo', default='off', choices=['off', 'on', 'append']) diff -r 622af5fb8c58 -r 1ceb90be7bac mx/projects --- a/mx/projects Fri Jan 03 16:38:57 2014 -0800 +++ b/mx/projects Mon Jan 06 14:30:23 2014 -0800 @@ -26,6 +26,47 @@ library@OKRA@path=lib/okra-1.2.jar library@OKRA@urls=http://cr.openjdk.java.net/~tdeneau/okra-1.2.jar +library@JRUBYPARSER@path=lib/jrubyparser-0.5.0.jar +library@JRUBYPARSER@urls=http://repo1.maven.org/maven2/org/jruby/jrubyparser/0.5.0/jrubyparser-0.5.0.jar + +library@JLINE@path=lib/jline-2.10.jar +library@JLINE@urls=http://repo1.maven.org/maven2/jline/jline/2.10/jline-2.10.jar + +library@JRUBYSTDLIB@path=lib/jruby-stdlib-1.7.4.jar +library@JRUBYSTDLIB@urls=http://repo1.maven.org/maven2/org/jruby/jruby-stdlib/1.7.4/jruby-stdlib-1.7.4.jar + +library@JNR_POSIX@path=lib/jnr-posix-3.0.0.jar +library@JNR_POSIX@urls=http://repo1.maven.org/maven2/com/github/jnr/jnr-posix/3.0.0/jnr-posix-3.0.0.jar + +library@JNR_CONSTANTS@path=lib/jnr-constants-0.8.4.jar +library@JNR_CONSTANTS@urls=http://repo1.maven.org/maven2/com/github/jnr/jnr-constants/0.8.4/jnr-constants-0.8.4.jar + +library@JNR_FFI@path=lib/jnr-ffi-1.0.4.jar +library@JNR_FFI@urls=http://repo1.maven.org/maven2/com/github/jnr/jnr-ffi/1.0.4/jnr-ffi-1.0.4.jar + +library@JFFI@path=lib/jffi-1.2.1.jar +library@JFFI@urls=http://repo1.maven.org/maven2/com/github/jnr/jffi/1.2.1/jffi-1.2.1.jar + +library@JFFI_NATIVE@path=lib/jffi-1.2.1-native.jar +library@JFFI_NATIVE@urls=http://search.maven.org/remotecontent?filepath=com/github/jnr/jffi/1.2.1/jffi-1.2.1-native.jar + +library@JNR_X86ASM@path=lib/jnr-x86asm-1.0.2.jar +library@JNR_X86ASM@urls=http://repo1.maven.org/maven2/com/github/jnr/jnr-x86asm/1.0.2/jnr-x86asm-1.0.2.jar + +library@ASM@path=lib/asm-4.0.jar +library@ASM@urls=http://repo1.maven.org/maven2/org/ow2/asm/asm/4.0/asm-4.0.jar + +library@ASM_ANALYSIS@path=lib/asm-analysis-4.0.jar +library@ASM_ANALYSIS@urls=http://repo1.maven.org/maven2/org/ow2/asm/asm-analysis/4.0/asm-analysis-4.0.jar + +library@ASM_COMMONS@path=lib/asm-commons-4.0.jar +library@ASM_COMMONS@urls=http://repo1.maven.org/maven2/org/ow2/asm/asm-commons/4.0/asm-commons-4.0.jar + +library@ASM_TREE@path=lib/asm-tree-4.0.jar +library@ASM_TREE@urls=http://repo1.maven.org/maven2/org/ow2/asm/asm-tree/4.0/asm-tree-4.0.jar + +library@ASM_UTIL@path=lib/asm-util-4.0.jar +library@ASM_UTIL@urls=http://repo1.maven.org/maven2/org/ow2/asm/asm-util/4.0/asm-util-4.0.jar distribution@GRAAL@path=graal.jar distribution@GRAAL@dependencies=\ @@ -691,3 +732,43 @@ project@com.oracle.graal.truffle.hotspot.amd64@javaCompliance=1.7 project@com.oracle.graal.truffle.hotspot.amd64@annotationProcessors=com.oracle.graal.service.processor project@com.oracle.graal.truffle.hotspot.amd64@workingSets=Graal,Truffle + +# truffle.ruby.runtime +project@com.oracle.truffle.ruby.runtime@subDir=graal +project@com.oracle.truffle.ruby.runtime@sourceDirs=src +project@com.oracle.truffle.ruby.runtime@dependencies=JRUBYSTDLIB,JNR_POSIX,JNR_CONSTANTS,JNR_FFI,JFFI,JFFI_NATIVE,JNR_X86ASM,ASM,ASM_ANALYSIS,ASM_COMMONS,ASM_TREE,ASM_UTIL,com.oracle.truffle.api +project@com.oracle.truffle.ruby.runtime@javaCompliance=1.7 +project@com.oracle.truffle.ruby.runtime@workingSets=Truffle,Ruby + +# truffle.ruby.nodes +project@com.oracle.truffle.ruby.nodes@subDir=graal +project@com.oracle.truffle.ruby.nodes@sourceDirs=src +project@com.oracle.truffle.ruby.nodes@dependencies=com.oracle.truffle.ruby.runtime,com.oracle.truffle.api.dsl +project@com.oracle.truffle.ruby.nodes@checkstyle=com.oracle.truffle.ruby.runtime +project@com.oracle.truffle.ruby.nodes@javaCompliance=1.7 +project@com.oracle.truffle.ruby.nodes@annotationProcessors=com.oracle.truffle.dsl.processor +project@com.oracle.truffle.ruby.nodes@workingSets=Truffle,Ruby + +# truffle.ruby.parser +project@com.oracle.truffle.ruby.parser@subDir=graal +project@com.oracle.truffle.ruby.parser@sourceDirs=src +project@com.oracle.truffle.ruby.parser@dependencies=JRUBYPARSER,com.oracle.truffle.ruby.nodes +project@com.oracle.truffle.ruby.parser@checkstyle=com.oracle.truffle.ruby.runtime +project@com.oracle.truffle.ruby.parser@javaCompliance=1.7 +project@com.oracle.truffle.ruby.parser@workingSets=Truffle,Ruby + +# truffle.ruby.shell +project@com.oracle.truffle.ruby.shell@subDir=graal +project@com.oracle.truffle.ruby.shell@sourceDirs=src +project@com.oracle.truffle.ruby.shell@dependencies=JLINE,com.oracle.truffle.ruby.parser +project@com.oracle.truffle.ruby.shell@checkstyle=com.oracle.truffle.ruby.runtime +project@com.oracle.truffle.ruby.shell@javaCompliance=1.7 +project@com.oracle.truffle.ruby.shell@workingSets=Truffle,Ruby + +# truffle.ruby.test +project@com.oracle.truffle.ruby.test@subDir=graal +project@com.oracle.truffle.ruby.test@sourceDirs=src +project@com.oracle.truffle.ruby.test@dependencies=com.oracle.truffle.ruby.parser,JUNIT +project@com.oracle.truffle.ruby.test@checkstyle=com.oracle.truffle.ruby.runtime +project@com.oracle.truffle.ruby.test@javaCompliance=1.7 +project@com.oracle.truffle.ruby.test@workingSets=Truffle,Ruby,Test diff -r 622af5fb8c58 -r 1ceb90be7bac mxtool/.pylintrc --- a/mxtool/.pylintrc Fri Jan 03 16:38:57 2014 -0800 +++ b/mxtool/.pylintrc Mon Jan 06 14:30:23 2014 -0800 @@ -44,7 +44,9 @@ too-many-lines,missing-docstring,no-init,no-self-use,too-many-statements, too-many-locals,too-few-public-methods,too-many-instance-attributes, too-many-arguments,too-many-branches,too-many-public-methods, - abstract-method + abstract-method,F0401 + +# F0401: http://www.logilab.org/ticket/9386 [REPORTS] diff -r 622af5fb8c58 -r 1ceb90be7bac src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp --- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Fri Jan 03 16:38:57 2014 -0800 +++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Mon Jan 06 14:30:23 2014 -0800 @@ -1601,7 +1601,7 @@ } #endif // TIERED __ set((intptr_t)os::get_polling_page(), L0); - __ relocate(relocInfo::poll_return_type); + __ relocate(poll_return_Relocation::spec(poll_Relocation::absolute)); __ ld_ptr(L0, 0, G0); __ ret(); __ delayed()->restore(); @@ -1613,7 +1613,7 @@ if (info != NULL) { add_debug_info_for_branch(info); } else { - __ relocate(relocInfo::poll_type); + __ relocate(poll_Relocation::spec(poll_Relocation::absolute)); } int offset = __ offset(); diff -r 622af5fb8c58 -r 1ceb90be7bac src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp --- a/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp Fri Jan 03 16:38:57 2014 -0800 +++ b/src/cpu/sparc/vm/graalCodeInstaller_sparc.hpp Mon Jan 06 14:30:23 2014 -0800 @@ -188,13 +188,13 @@ fatal("unimplemented"); } case MARK_POLL_FAR: - _instructions->relocate(pc, relocInfo::poll_type); + _instructions->relocate(pc, poll_Relocation::spec(poll_Relocation::absolute)); break; case MARK_POLL_RETURN_NEAR: { fatal("unimplemented"); } case MARK_POLL_RETURN_FAR: - _instructions->relocate(pc, relocInfo::poll_return_type); + _instructions->relocate(pc, poll_return_Relocation::spec(poll_Relocation::absolute)); break; default: fatal("invalid mark value"); diff -r 622af5fb8c58 -r 1ceb90be7bac src/cpu/sparc/vm/relocInfo_sparc.cpp --- a/src/cpu/sparc/vm/relocInfo_sparc.cpp Fri Jan 03 16:38:57 2014 -0800 +++ b/src/cpu/sparc/vm/relocInfo_sparc.cpp Mon Jan 06 14:30:23 2014 -0800 @@ -196,8 +196,5 @@ void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { } -void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { -} - void metadata_Relocation::pd_fix_value(address x) { } diff -r 622af5fb8c58 -r 1ceb90be7bac src/cpu/x86/vm/assembler_x86.cpp --- a/src/cpu/x86/vm/assembler_x86.cpp Fri Jan 03 16:38:57 2014 -0800 +++ b/src/cpu/x86/vm/assembler_x86.cpp Mon Jan 06 14:30:23 2014 -0800 @@ -81,8 +81,10 @@ _rspec = runtime_call_Relocation::spec(); break; case relocInfo::poll_type: + _rspec = poll_Relocation::spec(Assembler::is_polling_page_far() ? poll_Relocation::absolute : poll_Relocation::pc_relative); + break; case relocInfo::poll_return_type: - _rspec = Relocation::spec_simple(rtype); + _rspec = poll_return_Relocation::spec(Assembler::is_polling_page_far() ? poll_Relocation::absolute : poll_Relocation::pc_relative); break; case relocInfo::none: break; diff -r 622af5fb8c58 -r 1ceb90be7bac src/cpu/x86/vm/graalCodeInstaller_x86.hpp --- a/src/cpu/x86/vm/graalCodeInstaller_x86.hpp Fri Jan 03 16:38:57 2014 -0800 +++ b/src/cpu/x86/vm/graalCodeInstaller_x86.hpp Mon Jan 06 14:30:23 2014 -0800 @@ -232,15 +232,19 @@ switch (mark) { case MARK_POLL_NEAR: { relocate_poll_near(pc); + _instructions->relocate(pc, poll_Relocation::spec(poll_Relocation::pc_relative)); + break; } case MARK_POLL_FAR: - _instructions->relocate(pc, relocInfo::poll_type); + _instructions->relocate(pc, poll_Relocation::spec(poll_Relocation::absolute)); break; case MARK_POLL_RETURN_NEAR: { relocate_poll_near(pc); + _instructions->relocate(pc, poll_return_Relocation::spec(poll_Relocation::pc_relative)); + break; } case MARK_POLL_RETURN_FAR: - _instructions->relocate(pc, relocInfo::poll_return_type); + _instructions->relocate(pc, poll_return_Relocation::spec(poll_Relocation::absolute)); break; default: fatal("invalid mark value"); diff -r 622af5fb8c58 -r 1ceb90be7bac src/cpu/x86/vm/relocInfo_x86.cpp --- a/src/cpu/x86/vm/relocInfo_x86.cpp Fri Jan 03 16:38:57 2014 -0800 +++ b/src/cpu/x86/vm/relocInfo_x86.cpp Mon Jan 06 14:30:23 2014 -0800 @@ -179,29 +179,7 @@ void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { #ifdef _LP64 - if (!Assembler::is_polling_page_far()) { - typedef Assembler::WhichOperand WhichOperand; - WhichOperand which = (WhichOperand) format(); - // This format is imm but it is really disp32 - which = Assembler::disp32_operand; - address orig_addr = old_addr_for(addr(), src, dest); - NativeInstruction* oni = nativeInstruction_at(orig_addr); - int32_t* orig_disp = (int32_t*) Assembler::locate_operand(orig_addr, which); - // This poll_addr is incorrect by the size of the instruction it is irrelevant - intptr_t poll_addr = (intptr_t)oni + *orig_disp; - - NativeInstruction* ni = nativeInstruction_at(addr()); - intptr_t new_disp = poll_addr - (intptr_t) ni; - - int32_t* disp = (int32_t*) Assembler::locate_operand(addr(), which); - * disp = (int32_t)new_disp; - } -#endif // _LP64 -} - -void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { -#ifdef _LP64 - if (!Assembler::is_polling_page_far()) { + if (_form == pc_relative) { typedef Assembler::WhichOperand WhichOperand; WhichOperand which = (WhichOperand) format(); // This format is imm but it is really disp32 diff -r 622af5fb8c58 -r 1ceb90be7bac src/share/vm/code/relocInfo.cpp --- a/src/share/vm/code/relocInfo.cpp Fri Jan 03 16:38:57 2014 -0800 +++ b/src/share/vm/code/relocInfo.cpp Mon Jan 06 14:30:23 2014 -0800 @@ -679,6 +679,16 @@ _target = address_from_scaled_offset(offset, base); } +void poll_Relocation::pack_data_to(CodeSection* dest) { + short* p = (short*) dest->locs_end(); + p = pack_1_int_to(p, _form); + dest->set_locs_end((relocInfo*) p); +} + +void poll_Relocation::unpack_data() { + _form = (poll_Relocation::pollingForm) unpack_1_int(); +} + //// miscellaneous methods oop* oop_Relocation::oop_addr() { int n = _oop_index; @@ -975,6 +985,22 @@ tty->print(" | [static_call=" INTPTR_FORMAT "]", r->static_call()); break; } + case relocInfo::poll_type: + case relocInfo::poll_return_type: + { + poll_Relocation* r = (poll_Relocation*) reloc(); + const char *formName = "unknown"; + switch (r->form()) { + case poll_Relocation::pc_relative: + formName = "pc_relative"; + break; + case poll_Relocation::absolute: + formName = "absolute"; + break; + } + tty->print(" | [form=%d(%s)]", r->form(), formName); + break; + } } tty->cr(); } diff -r 622af5fb8c58 -r 1ceb90be7bac src/share/vm/code/relocInfo.hpp --- a/src/share/vm/code/relocInfo.hpp Fri Jan 03 16:38:57 2014 -0800 +++ b/src/share/vm/code/relocInfo.hpp Mon Jan 06 14:30:23 2014 -0800 @@ -210,6 +210,12 @@ // See [About Offsets] below. // //%note reloc_2 // +// relocInfo::poll_[return_]type -- a safepoint poll +// Value: none +// Instruction types: memory load or test +// Data: [] the associated set-oops are adjacent to the call +// [n] n is a poll_Relocation::pollingForm value +// // For example: // // INSTRUCTIONS RELOC: TYPE PREFIX DATA @@ -1271,17 +1277,53 @@ section_word_Relocation() { } }; - class poll_Relocation : public Relocation { + public: + enum pollingForm { + pc_relative, + absolute + }; + relocInfo::relocType type() { return relocInfo::poll_type; } bool is_data() { return true; } - relocInfo::relocType type() { return relocInfo::poll_type; } void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest); + private: + pollingForm _form; + public: + + static RelocationHolder spec(poll_Relocation::pollingForm form) { + RelocationHolder rh = newHolder(); + new(rh) poll_Relocation(form); + return rh; + } + + poll_Relocation(poll_Relocation::pollingForm form) { + _form = form; + } + poll_Relocation::pollingForm form() { return _form; } + + void pack_data_to(CodeSection* dest); + void unpack_data(); + + protected: + friend class RelocIterator; + poll_Relocation() { } }; -class poll_return_Relocation : public Relocation { - bool is_data() { return true; } +class poll_return_Relocation : public poll_Relocation { + public: relocInfo::relocType type() { return relocInfo::poll_return_type; } - void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest); + + static RelocationHolder spec(poll_Relocation::pollingForm distance) { + RelocationHolder rh = newHolder(); + new(rh) poll_return_Relocation(distance); + return rh; + } + + poll_return_Relocation(poll_Relocation::pollingForm distance) : poll_Relocation(distance) { } + + private: + friend class RelocIterator; + poll_return_Relocation() { } }; // We know all the xxx_Relocation classes, so now we can define these: diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/BatikSVGProxy/build.xml --- a/visualizer/BatikSVGProxy/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project com.sun.hotspot.igv.svg. - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/BatikSVGProxy/manifest.mf --- a/visualizer/BatikSVGProxy/manifest.mf Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.sun.hotspot.igv.svg -OpenIDE-Module-Layer: com/sun/hotspot/igv/svg/layer.xml -OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/svg/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/BatikSVGProxy/nbproject/build-impl.xml --- a/visualizer/BatikSVGProxy/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ - - - - - - - - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/BatikSVGProxy/nbproject/genfiles.properties --- a/visualizer/BatikSVGProxy/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=ebcf0422 -nbproject/build-impl.xml.script.CRC32=42ef3ff6 -nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/BatikSVGProxy/nbproject/project.properties --- a/visualizer/BatikSVGProxy/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -javac.source=1.7 -javac.compilerargs=-Xlint -Xlint:-serial diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/BatikSVGProxy/nbproject/project.xml --- a/visualizer/BatikSVGProxy/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - com.sun.hotspot.igv.svg - - - - com.sun.hotspot.igv.svg - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/BatikSVGProxy/nbproject/suite.properties --- a/visualizer/BatikSVGProxy/nbproject/suite.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -suite.dir=${basedir}/.. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/BatikSVG.java --- a/visualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/BatikSVG.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.svg; - -import java.awt.Graphics2D; -import java.io.Writer; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import org.w3c.dom.DOMImplementation; - -/** - * Utility class - * @author Thomas Wuerthinger - */ -public class BatikSVG { - - private BatikSVG() { - } - - private static Constructor SVGGraphics2DConstructor; - private static Method streamMethod; - private static Method createDefaultMethod; - private static Method getDOMImplementationMethod; - private static Method setEmbeddedFontsOnMethod; - private static Class classSVGGraphics2D; - - /** - * Creates a graphics object that allows to be exported to SVG data using the {@link #printToStream(Graphics2D, Writer, boolean) printToStream} method. - * @return the newly created Graphics2D object or null if the library does not exist - */ - public static Graphics2D createGraphicsObject() { - try { - if (SVGGraphics2DConstructor == null) { - ClassLoader cl = BatikSVG.class.getClassLoader(); - Class classGenericDOMImplementation = cl.loadClass("org.apache.batik.dom.GenericDOMImplementation"); - Class classSVGGeneratorContext = cl.loadClass("org.apache.batik.svggen.SVGGeneratorContext"); - classSVGGraphics2D = cl.loadClass("org.apache.batik.svggen.SVGGraphics2D"); - getDOMImplementationMethod = classGenericDOMImplementation.getDeclaredMethod("getDOMImplementation", new Class[0]); - createDefaultMethod = classSVGGeneratorContext.getDeclaredMethod("createDefault", new Class[]{org.w3c.dom.Document.class}); - setEmbeddedFontsOnMethod = classSVGGeneratorContext.getDeclaredMethod("setEmbeddedFontsOn", new Class[]{boolean.class}); - streamMethod = classSVGGraphics2D.getDeclaredMethod("stream", Writer.class, boolean.class); - SVGGraphics2DConstructor = classSVGGraphics2D.getConstructor(classSVGGeneratorContext, boolean.class); - } - DOMImplementation dom = (DOMImplementation) getDOMImplementationMethod.invoke(null); - org.w3c.dom.Document document = dom.createDocument("http://www.w3.org/2000/svg", "svg", null); - Object ctx = createDefaultMethod.invoke(null, document); - setEmbeddedFontsOnMethod.invoke(ctx, true); - Graphics2D svgGenerator = (Graphics2D) SVGGraphics2DConstructor.newInstance(ctx, true); - return svgGenerator; - } catch (ClassNotFoundException e) { - return null; - } catch (NoSuchMethodException e) { - return null; - } catch (IllegalAccessException e) { - return null; - } catch (InvocationTargetException e) { - return null; - } catch (InstantiationException e) { - return null; - } - } - - /** - * Serializes a graphics object to a stream in SVG format. - * @param svgGenerator the graphics object. Only graphics objects created by the {@link #createGraphicsObject() createGraphicsObject} method are valid. - * @param stream the stream to which the data is written - * @param useCSS whether to use CSS styles in the SVG output - */ - public static void printToStream(Graphics2D svgGenerator, Writer stream, boolean useCSS) { - assert classSVGGraphics2D != null; - assert classSVGGraphics2D.isInstance(svgGenerator); - try { - streamMethod.invoke(svgGenerator, stream, useCSS); - } catch (IllegalAccessException e) { - assert false; - } catch (InvocationTargetException e) { - assert false; - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/Bundle.properties --- a/visualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -OpenIDE-Module-Name=BatikSVGProxy diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/layer.xml --- a/visualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/layer.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/package-info.java --- a/visualizer/BatikSVGProxy/src/com/sun/hotspot/igv/svg/package-info.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -/** - * This package is used to proxy the SVG export functionality of the BatikSVG library. Reflection is used such that the - * library is optional and need not be present at build time. - */ -package com.sun.hotspot.igv.svg; - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/build.xml --- a/visualizer/Bytecodes/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project com.sun.hotspot.igv.bytecodes. - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/manifest.mf --- a/visualizer/Bytecodes/manifest.mf Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.sun.hotspot.igv.bytecodes -OpenIDE-Module-Layer: com/sun/hotspot/igv/bytecodes/layer.xml -OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/bytecodes/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/nbproject/build-impl.xml --- a/visualizer/Bytecodes/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/nbproject/genfiles.properties --- a/visualizer/Bytecodes/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -build.xml.data.CRC32=1dee290d -build.xml.script.CRC32=d594034f -build.xml.stylesheet.CRC32=79c3b980 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=1dee290d -nbproject/build-impl.xml.script.CRC32=b4dab126 -nbproject/build-impl.xml.stylesheet.CRC32=deb65f65 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/nbproject/platform.properties --- a/visualizer/Bytecodes/nbproject/platform.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -# Deprecated since 5.0u1; for compatibility with 5.0: -disabled.clusters=\ - apisupport1,\ - harness,\ - ide8,\ - java1,\ - nb6.0,\ - profiler2 -disabled.modules=\ - org.netbeans.core.execution,\ - org.netbeans.core.multiview,\ - org.netbeans.core.output2,\ - org.netbeans.modules.applemenu,\ - org.netbeans.modules.autoupdate.services,\ - org.netbeans.modules.autoupdate.ui,\ - org.netbeans.modules.core.kit,\ - org.netbeans.modules.favorites,\ - org.netbeans.modules.javahelp,\ - org.netbeans.modules.masterfs,\ - org.netbeans.modules.options.keymap,\ - org.netbeans.modules.sendopts,\ - org.netbeans.modules.templates,\ - org.openide.compat,\ - org.openide.execution,\ - org.openide.util.enumerations -enabled.clusters=\ - platform7 -nbjdk.active=JDK_1.6 -nbplatform.active=default diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/nbproject/project.properties --- a/visualizer/Bytecodes/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -javac.source=1.7 -javac.compilerargs=-Xlint -Xlint:-serial diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/nbproject/project.xml --- a/visualizer/Bytecodes/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - com.sun.hotspot.igv.bytecodes - - - - com.sun.hotspot.igv.data - - - - 1.0 - - - - com.sun.hotspot.igv.graph - - - - 1.0 - - - - com.sun.hotspot.igv.util - - - - 1.0 - - - - org.jdesktop.layout - - - - 1 - 1.16.1 - - - - org.openide.explorer - - - - 6.34.1 - - - - org.openide.nodes - - - - 7.20.1 - - - - org.openide.util - - - - 8.14.1 - - - - org.openide.util.lookup - - - - 8.6.1 - - - - org.openide.windows - - - - 6.39.1 - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/nbproject/suite.properties --- a/visualizer/Bytecodes/nbproject/suite.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -suite.dir=${basedir}/.. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/Bundle.properties --- a/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -CTL_BytecodeViewAction=Bytecode -CTL_BytecodeViewTopComponent=Bytecode -CTL_SelectBytecodesAction=Select nodes -HINT_BytecodeViewTopComponent=Shows the bytecode associated with the displayed graph. -OpenIDE-Module-Name=Bytecodes diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeNode.java --- a/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeNode.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.bytecodes; - -import com.sun.hotspot.igv.data.InputBytecode; -import com.sun.hotspot.igv.data.InputGraph; -import com.sun.hotspot.igv.data.InputNode; -import com.sun.hotspot.igv.data.Properties; -import com.sun.hotspot.igv.data.Properties.StringPropertyMatcher; -import java.awt.Image; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; -import javax.swing.Action; -import org.openide.nodes.AbstractNode; -import org.openide.nodes.Children; -import org.openide.nodes.Node; -import org.openide.util.ImageUtilities; - -/** - * - * @author Thomas Wuerthinger - */ -public class BytecodeNode extends AbstractNode { - - private Set nodes; - - public BytecodeNode(InputBytecode bytecode, InputGraph graph, String bciValue) { - - super(Children.LEAF); - String displayName = bytecode.getBci() + " " + bytecode.getName() + " " + bytecode.getOperands(); - - bciValue = bytecode.getBci() + " " + bciValue; - bciValue = bciValue.trim(); - - Properties.PropertySelector selector = new Properties.PropertySelector<>(graph.getNodes()); - StringPropertyMatcher matcher = new StringPropertyMatcher("bci", bciValue); - List nodeList = selector.selectMultiple(matcher); - if (nodeList.size() > 0) { - nodes = new LinkedHashSet<>(); - for (InputNode n : nodeList) { - nodes.add(n); - } - displayName += " (" + nodes.size() + " nodes)"; - } - - if (bytecode.getComment() != null) { - displayName += " // " + bytecode.getComment(); - } - - this.setDisplayName(displayName); - } - - @Override - public Image getIcon(int i) { - if (nodes != null) { - return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/link.png"); - } else { - return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/bytecode.png"); - } - } - - @Override - public Image getOpenedIcon(int i) { - return getIcon(i); - } - - @Override - public Action[] getActions(boolean b) { - return new Action[]{(Action) SelectBytecodesAction.findObject(SelectBytecodesAction.class, true)}; - } - - @Override - public Action getPreferredAction() { - return (Action) SelectBytecodesAction.findObject(SelectBytecodesAction.class, true); - } - - @Override - @SuppressWarnings("unchecked") - public T getCookie(Class aClass) { - if (aClass == SelectBytecodesCookie.class && nodes != null) { - return (T) (new SelectBytecodesCookie(nodes)); - } - return super.getCookie(aClass); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewAction.java --- a/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.bytecodes; - -import java.awt.event.ActionEvent; -import javax.swing.AbstractAction; -import org.openide.util.NbBundle; -import org.openide.windows.TopComponent; - -/** - * @author Thomas Wuerthinger - */ -public class BytecodeViewAction extends AbstractAction { - - public BytecodeViewAction() { - super(NbBundle.getMessage(BytecodeViewAction.class, "CTL_BytecodeViewAction")); - } - - @Override - public void actionPerformed(ActionEvent evt) { - TopComponent win = BytecodeViewTopComponent.findInstance(); - win.open(); - win.requestActive(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.form --- a/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.form Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ - - -

- - - - - - - - - - - - - - - - - - - - - - - - -
diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.java --- a/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponent.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.bytecodes; - -import com.sun.hotspot.igv.data.Group; -import com.sun.hotspot.igv.data.InputGraph; -import com.sun.hotspot.igv.data.services.InputGraphProvider; -import java.awt.BorderLayout; -import java.io.Serializable; -import javax.swing.SwingUtilities; -import org.openide.ErrorManager; -import org.openide.explorer.ExplorerManager; -import org.openide.explorer.ExplorerUtils; -import org.openide.explorer.view.BeanTreeView; -import org.openide.util.*; -import org.openide.windows.TopComponent; -import org.openide.windows.WindowManager; - -/** - * @author Thomas Wuerthinger - */ -final class BytecodeViewTopComponent extends TopComponent implements ExplorerManager.Provider, LookupListener { - - private static BytecodeViewTopComponent instance; - private static final String PREFERRED_ID = "BytecodeViewTopComponent"; - private ExplorerManager manager; - private BeanTreeView treeView; - private Lookup.Result result = null; - private MethodNode rootNode; - - private BytecodeViewTopComponent() { - initComponents(); - setName(NbBundle.getMessage(BytecodeViewTopComponent.class, "CTL_BytecodeViewTopComponent")); - setToolTipText(NbBundle.getMessage(BytecodeViewTopComponent.class, "HINT_BytecodeViewTopComponent")); - - manager = new ExplorerManager(); - rootNode = new MethodNode(null, null, ""); - manager.setRootContext(rootNode); - - setLayout(new BorderLayout()); - - treeView = new BeanTreeView(); - treeView.setRootVisible(false); - this.add(BorderLayout.CENTER, treeView); - associateLookup(ExplorerUtils.createLookup(manager, getActionMap())); - } - - /** This method is called from within the constructor to - * initialize the form. - * WARNING: Do NOT modify this code. The content of this method is - * always regenerated by the Form Editor. - */ - // //GEN-BEGIN:initComponents - private void initComponents() { - - org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(0, 400, Short.MAX_VALUE) - ); - layout.setVerticalGroup( - layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(0, 300, Short.MAX_VALUE) - ); - }// //GEN-END:initComponents - // Variables declaration - do not modify//GEN-BEGIN:variables - // End of variables declaration//GEN-END:variables - - /** - * Gets default instance. Do not use directly: reserved for *.settings files only, - * i.e. deserialization routines; otherwise you could get a non-deserialized instance. - * To obtain the singleton instance, use {@link #findInstance}. - */ - public static synchronized BytecodeViewTopComponent getDefault() { - if (instance == null) { - instance = new BytecodeViewTopComponent(); - } - return instance; - } - - /** - * Obtain the BytecodeViewTopComponent instance. Never call {@link #getDefault} directly! - */ - public static synchronized BytecodeViewTopComponent findInstance() { - TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID); - if (win == null) { - ErrorManager.getDefault().log(ErrorManager.WARNING, "Cannot find BytecodeView component. It will not be located properly in the window system."); - return getDefault(); - } - if (win instanceof BytecodeViewTopComponent) { - return (BytecodeViewTopComponent) win; - } - ErrorManager.getDefault().log(ErrorManager.WARNING, "There seem to be multiple components with the '" + PREFERRED_ID + "' ID. That is a potential source of errors and unexpected behavior."); - return getDefault(); - } - - @Override - public int getPersistenceType() { - return TopComponent.PERSISTENCE_ALWAYS; - } - - @Override - public void componentOpened() { - Lookup.Template tpl = new Lookup.Template<>(InputGraphProvider.class); - result = Utilities.actionsGlobalContext().lookup(tpl); - result.addLookupListener(this); - } - - @Override - public void componentClosed() { - result.removeLookupListener(this); - result = null; - } - - @Override - public Object writeReplace() { - return new ResolvableHelper(); - } - - @Override - protected String preferredID() { - return PREFERRED_ID; - } - - @Override - public ExplorerManager getExplorerManager() { - return manager; - } - - @Override - public void requestActive() { - super.requestActive(); - this.treeView.requestFocus(); - } - - @Override - public boolean requestFocus(boolean temporary) { - this.treeView.requestFocus(); - return super.requestFocus(temporary); - } - - @Override - protected boolean requestFocusInWindow(boolean temporary) { - this.treeView.requestFocus(); - return super.requestFocusInWindow(temporary); - } - - @Override - public void resultChanged(LookupEvent lookupEvent) { - final InputGraphProvider p = null; // TODO(tw): FIXME //.getLast(InputGraphProvider.class);//)Utilities.actionsGlobalContext().lookup(InputGraphProvider.class); - if (p != null) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - InputGraph graph = p.getGraph(); - if (graph != null) { - Group g = graph.getGroup(); - rootNode.update(graph, g.getMethod()); - } - } - }); - } - } - - final static class ResolvableHelper implements Serializable { - - private static final long serialVersionUID = 1L; - - public Object readResolve() { - return BytecodeViewTopComponent.getDefault(); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponentSettings.xml --- a/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponentSettings.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponentWstcref.xml --- a/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/BytecodeViewTopComponentWstcref.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/MethodNode.java --- a/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/MethodNode.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.bytecodes; - -import com.sun.hotspot.igv.data.InputBytecode; -import com.sun.hotspot.igv.data.InputGraph; -import com.sun.hotspot.igv.data.InputMethod; -import java.awt.Image; -import org.openide.nodes.AbstractNode; -import org.openide.nodes.Children; -import org.openide.nodes.Node; -import org.openide.util.ImageUtilities; - -/** - * - * @author Thomas Wuerthinger - */ -public class MethodNode extends AbstractNode { - - private static class MethodNodeChildren extends Children.Keys { - - private InputMethod method; - private InputGraph graph; - private String bciString; - - public MethodNodeChildren(InputMethod method, InputGraph graph, String bciString) { - this.method = method; - this.bciString = bciString; - this.graph = graph; - } - - @Override - protected Node[] createNodes(InputBytecode bc) { - if (bc.getInlined() == null) { - return new Node[]{new BytecodeNode(bc, graph, bciString)}; - } else { - return new Node[]{new BytecodeNode(bc, graph, bciString), new MethodNode(bc.getInlined(), graph, bc.getBci() + " " + bciString)}; - } - } - - @Override - public void addNotify() { - if (method != null) { - setKeys(method.getBytecodes()); - } - } - - public void setMethod(InputMethod method, InputGraph graph) { - this.method = method; - this.graph = graph; - addNotify(); - } - } - - /** Creates a new instance of MethodNode */ - public MethodNode(InputMethod method, InputGraph graph, String bciString) { - super((method != null && method.getBytecodes().size() == 0) ? Children.LEAF : new MethodNodeChildren(method, graph, bciString)); - if (method != null) { - this.setDisplayName(method.getName()); - } - } - - @Override - public Image getIcon(int i) { - return ImageUtilities.loadImage("com/sun/hotspot/igv/bytecodes/images/method.png"); - } - - @Override - public Image getOpenedIcon(int i) { - return getIcon(i); - } - - public void update(InputGraph graph, InputMethod method) { - ((MethodNodeChildren) this.getChildren()).setMethod(method, graph); - if (method != null) { - this.setDisplayName(method.getName()); - } - - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/SelectBytecodesAction.java --- a/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/SelectBytecodesAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.bytecodes; - -import com.sun.hotspot.igv.data.services.InputGraphProvider; -import org.openide.nodes.Node; -import org.openide.util.HelpCtx; -import org.openide.util.NbBundle; -import org.openide.util.actions.CookieAction; - -/** - * - * @author Thomas Wuerthinger - */ -public final class SelectBytecodesAction extends CookieAction { - - @Override - protected void performAction(Node[] activatedNodes) { - SelectBytecodesCookie c = activatedNodes[0].getCookie(SelectBytecodesCookie.class); - InputGraphProvider p = null; // TODO: fixme LookupHistory.getLast(InputGraphProvider.class);//Utilities.actionsGlobalContext().lookup(InputGraphProvider.class); - if (p != null) { - p.setSelectedNodes(c.getNodes()); - } - } - - @Override - protected int mode() { - return CookieAction.MODE_EXACTLY_ONE; - } - - @Override - public String getName() { - return NbBundle.getMessage(SelectBytecodesAction.class, "CTL_SelectBytecodesAction"); - } - - @Override - protected Class[] cookieClasses() { - return new Class[]{ - SelectBytecodesCookie.class - }; - } - - @Override - protected void initialize() { - super.initialize(); - putValue("noIconInMenu", Boolean.TRUE); - } - - @Override - public HelpCtx getHelpCtx() { - return HelpCtx.DEFAULT_HELP; - } - - @Override - protected boolean asynchronous() { - return false; - } -} - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/SelectBytecodesCookie.java --- a/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/SelectBytecodesCookie.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.bytecodes; - -import com.sun.hotspot.igv.data.InputNode; -import java.util.Collections; -import java.util.Set; -import org.openide.nodes.Node; - -/** - * - * @author Thomas Wuerthinger - */ -public class SelectBytecodesCookie implements Node.Cookie { - - private Set nodes; - - /** Creates a new instance of SelectBytecodesCookie */ - public SelectBytecodesCookie(Set nodes) { - this.nodes = nodes; - } - - public Set getNodes() { - return Collections.unmodifiableSet(nodes); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/bytecode.png Binary file visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/bytecode.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/link.png Binary file visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/link.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/method.png Binary file visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/images/method.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/layer.xml --- a/visualizer/Bytecodes/src/com/sun/hotspot/igv/bytecodes/layer.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/build.xml --- a/visualizer/ControlFlowEditor/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project at.ssw.visualizer.cfg. - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/manifest.mf --- a/visualizer/ControlFlowEditor/manifest.mf Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: at.ssw.visualizer.cfg -OpenIDE-Module-Layer: at/ssw/visualizer/cfg/layer.xml -OpenIDE-Module-Localizing-Bundle: at/ssw/visualizer/cfg/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/nbproject/build-impl.xml --- a/visualizer/ControlFlowEditor/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ - - - - - - - - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/nbproject/genfiles.properties --- a/visualizer/ControlFlowEditor/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -build.xml.data.CRC32=d86dea19 -build.xml.script.CRC32=ec651852 -build.xml.stylesheet.CRC32=a56c6a5b@2.47.1 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=d86dea19 -nbproject/build-impl.xml.script.CRC32=d9cb852b -nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/nbproject/platform.properties --- a/visualizer/ControlFlowEditor/nbproject/platform.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,204 +0,0 @@ -cluster.path=\ - ${nbplatform.active.dir}/ide:\ - ${nbplatform.active.dir}/platform -disabled.modules=\ - com.jcraft.jsch,\ - com.jcraft.jzlib,\ - org.apache.commons.codec,\ - org.apache.commons.httpclient,\ - org.apache.commons.io,\ - org.apache.commons.lang,\ - org.apache.commons.logging,\ - org.apache.ws.commons.util,\ - org.apache.xml.resolver,\ - org.apache.xmlrpc,\ - org.eclipse.core.contenttype,\ - org.eclipse.core.jobs,\ - org.eclipse.core.net,\ - org.eclipse.core.runtime,\ - org.eclipse.core.runtime.compatibility.auth,\ - org.eclipse.equinox.app,\ - org.eclipse.equinox.common,\ - org.eclipse.equinox.preferences,\ - org.eclipse.equinox.registry,\ - org.eclipse.equinox.security,\ - org.eclipse.jgit,\ - org.eclipse.mylyn.bugzilla.core,\ - org.eclipse.mylyn.commons.core,\ - org.eclipse.mylyn.commons.net,\ - org.eclipse.mylyn.commons.xmlrpc,\ - org.eclipse.mylyn.tasks.core,\ - org.mozilla.rhino.patched,\ - org.netbeans.api.debugger,\ - org.netbeans.api.java.classpath,\ - org.netbeans.api.xml,\ - org.netbeans.core.browser,\ - org.netbeans.core.execution,\ - org.netbeans.core.ide,\ - org.netbeans.core.io.ui,\ - org.netbeans.core.multiview,\ - org.netbeans.core.nativeaccess,\ - org.netbeans.core.osgi,\ - org.netbeans.lib.cvsclient,\ - org.netbeans.lib.terminalemulator,\ - org.netbeans.libs.antlr3.runtime,\ - org.netbeans.libs.bytelist,\ - org.netbeans.libs.commons_net,\ - org.netbeans.libs.freemarker,\ - org.netbeans.libs.git,\ - org.netbeans.libs.ini4j,\ - org.netbeans.libs.jaxb,\ - org.netbeans.libs.jsr223,\ - org.netbeans.libs.junit4,\ - org.netbeans.libs.jvyamlb,\ - org.netbeans.libs.lucene,\ - org.netbeans.libs.smack,\ - org.netbeans.libs.svnClientAdapter,\ - org.netbeans.libs.svnClientAdapter.javahl,\ - org.netbeans.libs.svnClientAdapter.svnkit,\ - org.netbeans.libs.swingx,\ - org.netbeans.libs.xerces,\ - org.netbeans.modules.autoupdate.services,\ - org.netbeans.modules.autoupdate.ui,\ - org.netbeans.modules.bugtracking,\ - org.netbeans.modules.bugtracking.bridge,\ - org.netbeans.modules.bugzilla,\ - org.netbeans.modules.core.kit,\ - org.netbeans.modules.csl.api,\ - org.netbeans.modules.css.editor,\ - org.netbeans.modules.css.lib,\ - org.netbeans.modules.css.visual,\ - org.netbeans.modules.db,\ - org.netbeans.modules.db.core,\ - org.netbeans.modules.db.dataview,\ - org.netbeans.modules.db.drivers,\ - org.netbeans.modules.db.kit,\ - org.netbeans.modules.db.metadata.model,\ - org.netbeans.modules.db.mysql,\ - org.netbeans.modules.db.sql.editor,\ - org.netbeans.modules.db.sql.visualeditor,\ - org.netbeans.modules.dbapi,\ - org.netbeans.modules.defaults,\ - org.netbeans.modules.derby,\ - org.netbeans.modules.dlight.nativeexecution,\ - org.netbeans.modules.dlight.terminal,\ - org.netbeans.modules.editor.bookmarks,\ - org.netbeans.modules.editor.bracesmatching,\ - org.netbeans.modules.editor.codetemplates,\ - org.netbeans.modules.editor.completion,\ - org.netbeans.modules.editor.guards,\ - org.netbeans.modules.editor.indent.project,\ - org.netbeans.modules.editor.kit,\ - org.netbeans.modules.editor.macros,\ - org.netbeans.modules.editor.structure,\ - org.netbeans.modules.extbrowser,\ - org.netbeans.modules.extexecution,\ - org.netbeans.modules.extexecution.destroy,\ - org.netbeans.modules.favorites,\ - org.netbeans.modules.git,\ - org.netbeans.modules.glassfish.common,\ - org.netbeans.modules.gototest,\ - org.netbeans.modules.gsf.codecoverage,\ - org.netbeans.modules.gsf.testrunner,\ - org.netbeans.modules.html,\ - org.netbeans.modules.html.editor,\ - org.netbeans.modules.html.editor.lib,\ - org.netbeans.modules.html.lexer,\ - org.netbeans.modules.html.parser,\ - org.netbeans.modules.html.validation,\ - org.netbeans.modules.httpserver,\ - org.netbeans.modules.hudson,\ - org.netbeans.modules.hudson.git,\ - org.netbeans.modules.hudson.mercurial,\ - org.netbeans.modules.hudson.subversion,\ - org.netbeans.modules.hudson.tasklist,\ - org.netbeans.modules.ide.kit,\ - org.netbeans.modules.image,\ - org.netbeans.modules.javascript.editing,\ - org.netbeans.modules.javascript.hints,\ - org.netbeans.modules.javascript.kit,\ - org.netbeans.modules.javascript.refactoring,\ - org.netbeans.modules.jellytools.ide,\ - org.netbeans.modules.jumpto,\ - org.netbeans.modules.keyring.impl,\ - org.netbeans.modules.languages,\ - org.netbeans.modules.languages.diff,\ - org.netbeans.modules.languages.manifest,\ - org.netbeans.modules.languages.yaml,\ - org.netbeans.modules.lexer.nbbridge,\ - org.netbeans.modules.localhistory,\ - org.netbeans.modules.mercurial,\ - org.netbeans.modules.netbinox,\ - org.netbeans.modules.parsing.api,\ - org.netbeans.modules.parsing.lucene,\ - org.netbeans.modules.print.editor,\ - org.netbeans.modules.project.ant,\ - org.netbeans.modules.project.libraries,\ - org.netbeans.modules.projectui,\ - org.netbeans.modules.projectui.buildmenu,\ - org.netbeans.modules.projectuiapi,\ - org.netbeans.modules.properties,\ - org.netbeans.modules.properties.syntax,\ - org.netbeans.modules.refactoring.api,\ - org.netbeans.modules.schema2beans,\ - org.netbeans.modules.server,\ - org.netbeans.modules.servletapi,\ - org.netbeans.modules.spellchecker,\ - org.netbeans.modules.spellchecker.apimodule,\ - org.netbeans.modules.spellchecker.bindings.htmlxml,\ - org.netbeans.modules.spellchecker.bindings.properties,\ - org.netbeans.modules.spellchecker.dictionary_en,\ - org.netbeans.modules.spellchecker.kit,\ - org.netbeans.modules.spi.actions,\ - org.netbeans.modules.subversion,\ - org.netbeans.modules.swing.validation,\ - org.netbeans.modules.target.iterator,\ - org.netbeans.modules.tasklist.kit,\ - org.netbeans.modules.tasklist.projectint,\ - org.netbeans.modules.tasklist.todo,\ - org.netbeans.modules.tasklist.ui,\ - org.netbeans.modules.terminal,\ - org.netbeans.modules.usersguide,\ - org.netbeans.modules.utilities,\ - org.netbeans.modules.utilities.project,\ - org.netbeans.modules.versioning,\ - org.netbeans.modules.versioning.indexingbridge,\ - org.netbeans.modules.versioning.system.cvss.installer,\ - org.netbeans.modules.versioning.util,\ - org.netbeans.modules.web.client.tools.api,\ - org.netbeans.modules.web.common,\ - org.netbeans.modules.web.indent,\ - org.netbeans.modules.xml,\ - org.netbeans.modules.xml.axi,\ - org.netbeans.modules.xml.catalog,\ - org.netbeans.modules.xml.core,\ - org.netbeans.modules.xml.jaxb.api,\ - org.netbeans.modules.xml.lexer,\ - org.netbeans.modules.xml.multiview,\ - org.netbeans.modules.xml.retriever,\ - org.netbeans.modules.xml.schema.completion,\ - org.netbeans.modules.xml.schema.model,\ - org.netbeans.modules.xml.tax,\ - org.netbeans.modules.xml.text,\ - org.netbeans.modules.xml.tools,\ - org.netbeans.modules.xml.wsdl.model,\ - org.netbeans.modules.xml.xam,\ - org.netbeans.modules.xml.xdm,\ - org.netbeans.modules.xsl,\ - org.netbeans.spi.debugger.ui,\ - org.netbeans.spi.editor.hints,\ - org.netbeans.spi.navigator,\ - org.netbeans.spi.palette,\ - org.netbeans.spi.tasklist,\ - org.netbeans.spi.viewmodel,\ - org.netbeans.swing.dirchooser,\ - org.openide.compat,\ - org.openide.execution,\ - org.openide.options,\ - org.openide.util.enumerations -## Not disabled because of NetBeans bug 206347: -## Applications not using OSGi don't start on NbP 7.1 -# org.netbeans.core.netigso,\ -# org.netbeans.libs.felix,\ -# org.netbeans.libs.osgi,\ -nbplatform.active=default diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/nbproject/project.properties --- a/visualizer/ControlFlowEditor/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -javac.source=1.7 -javac.compilerargs=-Xlint -Xlint:-serial diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/nbproject/project.xml --- a/visualizer/ControlFlowEditor/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,146 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - at.ssw.visualizer.cfg - - - - com.oracle.graal.visualizer.editor - - - - 1.0 - - - - com.oracle.graal.visualizer.sharedactions - - - - 1.0 - - - - com.sun.hotspot.igv.data - - - - 1.0 - - - - org.eclipse.draw2d - - - - 1.0 - - - - org.jdesktop.layout - - - - 1 - 1.4.1 - - - - org.netbeans.api.visual - - - - 2.9.1 - - - - org.netbeans.modules.options.api - - - - 1 - 1.5 - - - - org.netbeans.modules.projectapi - - - - 1 - 1.40.1 - - - - org.openide.actions - - - - 6.6.1.1 - - - - org.openide.awt - - - - 6.11.1.1 - - - - org.openide.dialogs - - - - 7.5 - - - - org.openide.loaders - - - - 6.5 - - - - org.openide.nodes - - - - 7.2.0.1 - - - - org.openide.util - - - - 7.9.0.1 - - - - org.openide.util.lookup - - - - 8.3.1 - - - - org.openide.windows - - - - 6.16 - - - - - at.ssw.visualizer.cfg - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/nbproject/suite.properties --- a/visualizer/ControlFlowEditor/nbproject/suite.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -suite.dir=${basedir}/.. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/META-INF/services/com.oracle.graal.visualizer.editor.CompilationViewerFactory --- a/visualizer/ControlFlowEditor/src/META-INF/services/com.oracle.graal.visualizer.editor.CompilationViewerFactory Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -at.ssw.visualizer.cfg.CfgCompilationViewerFactory \ No newline at end of file diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/Bundle.properties --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -OpenIDE-Module-Name=ControlFlowEditor diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/CfgCompilationViewer.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/CfgCompilationViewer.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,235 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package at.ssw.visualizer.cfg; - -import at.ssw.visualizer.cfg.action.*; -import at.ssw.visualizer.cfg.graph.CfgScene; -import at.ssw.visualizer.cfg.graph.EdgeWidget; -import at.ssw.visualizer.cfg.graph.NodeWidget; -import at.ssw.visualizer.cfg.model.CfgEdge; -import at.ssw.visualizer.cfg.model.CfgNode; -import at.ssw.visualizer.cfg.preferences.CfgPreferences; -import at.ssw.visualizer.cfg.preferences.FlagsSetting; -import at.ssw.visualizer.model.cfg.ControlFlowGraph; -import com.oracle.graal.visualizer.editor.CompilationViewer; -import com.sun.hotspot.igv.data.InputGraph; -import java.awt.Color; -import java.awt.Component; -import java.beans.PropertyChangeEvent; -import javax.swing.*; -import javax.swing.border.Border; -import org.netbeans.api.visual.widget.Widget; -import org.openide.awt.Toolbar; -import org.openide.util.Lookup; -import org.openide.util.actions.SystemAction; -import org.openide.util.lookup.Lookups; - -class CfgCompilationViewer implements CompilationViewer { - - private CfgScene scene; - private JScrollPane jScrollPane; - private ControlFlowGraph cfg; - private JComponent myView; - - public CfgCompilationViewer(InputGraph cfg) { - this.cfg = cfg; - - // setIcon(ImageUtilities.loadImage("at/ssw/visualizer/cfg/icons/cfg.gif")); -// setName(cfg.getParent().getShortName()); -// setToolTipText(cfg.getCompilation().getMethod() + " - " + cfg.getName()); - // TODO(tw): Add title. - - //panel setup - this.jScrollPane = new JScrollPane(); - this.jScrollPane.setOpaque(true); - this.jScrollPane.setBorder(BorderFactory.createEmptyBorder()); - this.jScrollPane.setViewportBorder(BorderFactory.createEmptyBorder()); - this.scene = new CfgScene(jScrollPane, cfg); - this.myView = scene.createView(); - this.jScrollPane.setViewportView(myView); - jScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); - jScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); - jScrollPane.getVerticalScrollBar().setEnabled(true); - jScrollPane.getHorizontalScrollBar().setEnabled(true); - - //setup enviroment,register listeners - // TODO(tw): Add to lookup. -// selection = new Selection(); -// selection.put(cfg); -// selection.put(scene); -// selection.addChangeListener(scene); - - scene.validate(); - scene.applyLayout(); - } - - public void propertyChange(PropertyChangeEvent evt) { - if (this.scene != null) { - - String propName = evt.getPropertyName(); - CfgPreferences prefs = CfgPreferences.getInstance(); - switch (propName) { - case CfgPreferences.PROP_BACKGROUND_COLOR: - scene.setBackground(prefs.getBackgroundColor()); - scene.revalidate(); - break; - case CfgPreferences.PROP_NODE_COLOR: - for (NodeWidget nw : scene.getNodeWidgets()) { - //only change the node color if its not a custom color - if (!nw.isNodeColorCustomized()) { - nw.setNodeColor(prefs.getNodeColor(), false); - } - } - break; - case CfgPreferences.PROP_EDGE_COLOR: - for (CfgEdge e : scene.getEdges()) { - if (!e.isBackEdge() && !e.isXhandler()) { - EdgeWidget w = (EdgeWidget) scene.findWidget(e); - w.setLineColor(prefs.getEdgeColor()); - } - } - break; - case CfgPreferences.PROP_BACK_EDGE_COLOR: - for (CfgEdge e : scene.getEdges()) { - if (e.isBackEdge()) { - EdgeWidget w = (EdgeWidget) scene.findWidget(e); - w.setLineColor(prefs.getBackedgeColor()); - } - } - break; - case CfgPreferences.PROP_EXCEPTION_EDGE_COLOR: - for (CfgEdge e : scene.getEdges()) { - if (e.isXhandler()) { - EdgeWidget w = (EdgeWidget) scene.findWidget(e); - w.setLineColor(prefs.getExceptionEdgeColor()); - } - } - break; - case CfgPreferences.PROP_BORDER_COLOR: - for (CfgNode n : scene.getNodes()) { - NodeWidget nw = (NodeWidget) scene.findWidget(n); - nw.setBorderColor(prefs.getBorderColor()); - } - break; - case CfgPreferences.PROP_TEXT_FONT: - for (CfgNode n : scene.getNodes()) { - NodeWidget nw = (NodeWidget) scene.findWidget(n); - nw.adjustFont(prefs.getTextFont()); - } - break; - case CfgPreferences.PROP_TEXT_COLOR: - for (CfgNode n : scene.getNodes()) { - NodeWidget nw = (NodeWidget) scene.findWidget(n); - nw.setForeground(prefs.getTextColor()); - } - break; - case CfgPreferences.PROP_FLAGS: - FlagsSetting fs = CfgPreferences.getInstance().getFlagsSetting(); - for (CfgNode n : scene.getNodes()) { - NodeWidget nw = (NodeWidget) scene.findWidget(n); - Color nodeColor = fs.getColor(n.getBasicBlock().getFlags()); - if (nodeColor != null) { - nw.setNodeColor(nodeColor, true); - } else { - nw.setNodeColor(CfgPreferences.getInstance().getNodeColor(), false); - } - } - break; - case CfgPreferences.PROP_SELECTION_COLOR_BG: - case CfgPreferences.PROP_SELECTION_COLOR_FG: - for (CfgNode n : scene.getNodes()) { - Widget w = scene.findWidget(n); - w.revalidate(); - } - break; - } - scene.validate(); - } - - } - - /*@Override - public Component getToolBarComponent() { - Toolbar tb = new Toolbar("CfgToolbar"); - - tb.setBorder((Border) UIManager.get("Nb.Editor.Toolbar.border")); - - //zoomin/zoomout buttons - tb.add(SystemAction.get(ZoominAction.class).getToolbarPresenter()); - tb.add(SystemAction.get(ZoomoutAction.class).getToolbarPresenter()); - tb.addSeparator(); - - //router buttons - ButtonGroup routerButtons = new ButtonGroup(); - UseDirectLineRouterAction direct = SystemAction.get(UseDirectLineRouterAction.class); - UseBezierRouterAction bezier = SystemAction.get(UseBezierRouterAction.class); - JToggleButton button = (JToggleButton) direct.getToolbarPresenter(); - button.getModel().setGroup(routerButtons); - button.setSelected(true); - tb.add(button); - button = (JToggleButton) bezier.getToolbarPresenter(); - button.getModel().setGroup(routerButtons); - tb.add(button); - tb.addSeparator(); - - //layout buttons - tb.add(SystemAction.get(HierarchicalNodeLayoutAction.class).getToolbarPresenter()); - tb.add(SystemAction.get(HierarchicalCompoundLayoutAction.class).getToolbarPresenter()); - - tb.addSeparator(); - tb.add(SystemAction.get(ShowAllAction.class).getToolbarPresenter()); - tb.addSeparator(); - - //cluster button - tb.add(SystemAction.get(SwitchLoopClustersAction.class).getToolbarPresenter()); - tb.addSeparator(); - - //show/hide edge button - tb.add(SystemAction.get(ShowEdgesAction.class).getToolbarPresenter()); - tb.add(SystemAction.get(HideEdgesAction.class).getToolbarPresenter()); - tb.addSeparator(); - - //color button - JComponent colorButton = SystemAction.get(ColorAction.class).getToolbarPresenter(); - scene.addCfgEventListener((CfgEventListener) colorButton); - tb.add(colorButton); - - //export button - tb.add(SystemAction.get(ExportAction.class).getToolbarPresenter()); - tb.doLayout(); - - return tb; - }*/ - - @Override - public Lookup getLookup() { - return Lookups.fixed(scene); - } - - @Override - public Component getComponent() { - return jScrollPane; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/CfgCompilationViewerFactory.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/CfgCompilationViewerFactory.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ - -package at.ssw.visualizer.cfg; - -import com.oracle.graal.visualizer.editor.CompilationViewer; -import com.oracle.graal.visualizer.editor.CompilationViewerFactory; -import com.oracle.graal.visualizer.editor.DiagramViewModel; -import com.oracle.graal.visualizer.editor.SplitCompilationViewerFactory; -import com.sun.hotspot.igv.data.InputGraph; - -public class CfgCompilationViewerFactory extends SplitCompilationViewerFactory { - - @Override - public String getName() { - return "CFG"; - } - - @Override - protected CompilationViewer createViewer(InputGraph graph) { - return new CfgCompilationViewer(graph); - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/CfgEditorContext.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/CfgEditorContext.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ - -package at.ssw.visualizer.cfg; - -public abstract class CfgEditorContext { - - public static final int LAYOUT_HIERARCHICALNODELAYOUT = 1; - public static final int LAYOUT_HIERARCHICALCOMPOUNDLAYOUT = 2; - - public static final int MAX_AUTOEDGESVISIBLE = 8; -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/AbstractCfgEditorAction.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/AbstractCfgEditorAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -package at.ssw.visualizer.cfg.action; - - -import at.ssw.visualizer.cfg.graph.CfgScene; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JMenuItem; -import org.openide.util.Utilities; -import org.openide.util.actions.CallableSystemAction; - -/** - * The common superclass of all concrete actions related to the CFG visualizer. - * - * @author Bernhard Stiftner - * @author Rumpfhuber Stefan - */ -public abstract class AbstractCfgEditorAction extends CallableSystemAction { - - CfgScene topComponent = null; - - public AbstractCfgEditorAction() { - setEnabled(false); - - } - - protected CfgScene getEditor() { - return Utilities.actionsGlobalContext().lookup(CfgScene.class); - } - - @Override - public JMenuItem getMenuPresenter() { - return new JMenuItem(this); - } - - - @Override - public JComponent getToolbarPresenter() { - JButton b = new JButton(this); - if (getIcon() != null) { - b.setText(null); - b.setToolTipText(getName()); - } - return b; - } - - - @Override - public JMenuItem getPopupPresenter() { - return new JMenuItem(this); - } - - - @Override - protected boolean asynchronous() { - return false; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/Bundle.properties --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -CTL_SomeAction=test -CTL_SomeAction2=test diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/HideEdgesAction.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/HideEdgesAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package at.ssw.visualizer.cfg.action; - - -import at.ssw.visualizer.cfg.graph.CfgScene; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.List; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.awt.ActionRegistration; - -@ActionID(id = "at.ssw.visualizer.cfg.action.HideEdges", category = "View") -@ActionRegistration(displayName = "Hide Edges", iconBase="at/ssw/visualizer/cfg/icons/hideedges.gif") -@ActionReference(path = "CompilationViewer/CFG/Actions", position = 180) -public class HideEdgesAction implements ActionListener { - - private List scenes; - - public HideEdgesAction(List scenes) { - this.scenes = scenes; - } - - @Override - public void actionPerformed(ActionEvent e) { - for (CfgScene scene : scenes) { - scene.setSelectedEdgesVisibility(false); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/HierarchicalCompoundLayoutAction.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/HierarchicalCompoundLayoutAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package at.ssw.visualizer.cfg.action; - -import at.ssw.visualizer.cfg.CfgEditorContext; -import at.ssw.visualizer.cfg.graph.CfgScene; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.List; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.awt.ActionRegistration; - - -@ActionID(id = "at.ssw.visualizer.cfg.action.HierarchicalCompoundLayout", category = "View") -@ActionRegistration(displayName = "Compound Layout", iconBase="at/ssw/visualizer/cfg/icons/arrangeloop.gif") -@ActionReference(path = "CompilationViewer/CFG/Actions", position = 150) -public class HierarchicalCompoundLayoutAction implements ActionListener { - List scenes; - - public HierarchicalCompoundLayoutAction(List scenes) { - this.scenes = scenes; - } - - @Override - public void actionPerformed(ActionEvent e) { - for (CfgScene s : scenes) { - s.setSceneLayout(CfgEditorContext.LAYOUT_HIERARCHICALCOMPOUNDLAYOUT); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/HierarchicalNodeLayoutAction.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/HierarchicalNodeLayoutAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package at.ssw.visualizer.cfg.action; - -import at.ssw.visualizer.cfg.CfgEditorContext; -import at.ssw.visualizer.cfg.graph.CfgScene; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.List; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.awt.ActionRegistration; - - -@ActionID(id = "at.ssw.visualizer.cfg.action.HierarchicalNodeLayout", category = "View") -@ActionRegistration(displayName = "Layout", iconBase="at/ssw/visualizer/cfg/icons/arrangehier.gif") -@ActionReference(path = "CompilationViewer/CFG/Actions", position = 160) -public class HierarchicalNodeLayoutAction implements ActionListener { - List scenes; - - public HierarchicalNodeLayoutAction(List scenes) { - this.scenes = scenes; - } - - @Override - public void actionPerformed(ActionEvent e) { - for (CfgScene s : scenes) { - s.setSceneLayout(CfgEditorContext.LAYOUT_HIERARCHICALNODELAYOUT); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/ShowEdgesAction.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/action/ShowEdgesAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package at.ssw.visualizer.cfg.action; - -import at.ssw.visualizer.cfg.graph.CfgScene; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.List; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.awt.ActionRegistration; - - -@ActionID(id = "ShowEdges", category = "View") -@ActionRegistration(displayName = "Show Edges", iconBase="at/ssw/visualizer/cfg/icons/showedges.gif") -@ActionReference(path = "CompilationViewer/CFG/Actions", position = 170) -public class ShowEdgesAction implements ActionListener { - - private List scenes; - - public ShowEdgesAction(List scenes) { - this.scenes = scenes; - } - - @Override - public void actionPerformed(ActionEvent e) { - for (CfgScene scene : scenes) { - scene.setSelectedEdgesVisibility(true); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/CfgScene.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/CfgScene.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,836 +0,0 @@ -package at.ssw.visualizer.cfg.graph; - -import at.ssw.visualizer.cfg.model.CfgEdge; -import at.ssw.visualizer.cfg.CfgEditorContext; -import at.ssw.visualizer.cfg.action.HideEdgesAction; -import at.ssw.visualizer.cfg.action.ShowEdgesAction; -import at.ssw.visualizer.cfg.graph.layout.HierarchicalCompoundLayout; -import at.ssw.visualizer.cfg.graph.layout.HierarchicalNodeLayout; -import at.ssw.visualizer.cfg.model.CfgEnv; -import at.ssw.visualizer.cfg.model.CfgNode; -import at.ssw.visualizer.cfg.model.LoopInfo; -import at.ssw.visualizer.cfg.preferences.CfgPreferences; -import at.ssw.visualizer.cfg.visual.PolylineRouter; -import at.ssw.visualizer.cfg.visual.PolylineRouterV2; -import at.ssw.visualizer.cfg.visual.WidgetCollisionCollector; -import at.ssw.visualizer.model.cfg.BasicBlock; -import at.ssw.visualizer.model.cfg.ControlFlowGraph; -import com.oracle.graal.visualizer.sharedactions.ZoomCookie; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.RenderingHints; -import java.awt.event.ActionEvent; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.prefs.PreferenceChangeEvent; -import java.util.prefs.PreferenceChangeListener; -import java.util.prefs.Preferences; -import javax.swing.AbstractAction; -import javax.swing.JComponent; -import javax.swing.JMenu; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.event.EventListenerList; -import org.netbeans.api.visual.action.ActionFactory; -import org.netbeans.api.visual.action.MoveProvider; -import org.netbeans.api.visual.action.PopupMenuProvider; -import org.netbeans.api.visual.action.RectangularSelectDecorator; -import org.netbeans.api.visual.action.RectangularSelectProvider; -import org.netbeans.api.visual.action.WidgetAction; -import org.netbeans.api.visual.anchor.Anchor; -import org.netbeans.api.visual.anchor.AnchorFactory; -import org.netbeans.api.visual.graph.GraphScene; -import org.netbeans.api.visual.graph.layout.GraphLayout; -import org.netbeans.api.visual.layout.LayoutFactory; -import org.netbeans.api.visual.layout.SceneLayout; -import org.netbeans.api.visual.router.Router; -import org.netbeans.api.visual.router.Router.*; -import org.netbeans.api.visual.router.RouterFactory; -import org.netbeans.api.visual.widget.ConnectionWidget; -import org.netbeans.api.visual.widget.LayerWidget; -import org.netbeans.api.visual.widget.Widget; -import org.openide.util.NbPreferences; -import org.openide.util.actions.SystemAction; - -public final class CfgScene extends GraphScene implements ChangeListener, ZoomCookie { - - private LayerWidget mainLayer = new LayerWidget(this); - private LayerWidget connectionLayer = new LayerWidget(this); - private LayerWidget interractionLayer = new LayerWidget(this); - private LayerWidget clusterLayer = new LayerWidget(this); - private Set selectedNodes = Collections.emptySet(); - private Map loopidx2clusterwidget = new HashMap<>(); - private Map inputSwitches = new HashMap<>(); - private Map outputSwitches = new HashMap<>(); - private WidgetAction moveAction = ActionFactory.createMoveAction(ActionFactory.createFreeMoveStrategy(), this.createMoveProvider()); - private SceneLayout sceneLayout; - private CfgEnv env; - private int currentLayout = -1; - private JScrollPane scrollPane; - private WidgetAction contextPopupAction = this.createContextMenuAction(this); - private List nodeWidgets = null; - private boolean loopClustersVisible = true; - private static String PREFERENCE_LOOP_CLUSTER = "loopClusters"; - private static String PREFERENCE_ROUTER = "router"; - private static String PREFERENCE_LAYOUT = "layout"; - - public static Preferences getPreferences() { - return NbPreferences.forModule(CfgScene.class); - } - private final PreferenceChangeListener preferenceChangeListener = new PreferenceChangeListener() { - @Override - public void preferenceChange(PreferenceChangeEvent evt) { - if (evt.getKey().equals(PREFERENCE_ROUTER)) { - setUseBezierRouter(Boolean.parseBoolean(evt.getNewValue())); - } else if (evt.getKey().equals(PREFERENCE_LOOP_CLUSTER)) { - setLoopWidgets(Boolean.parseBoolean(evt.getNewValue())); - } - } - }; - - public CfgScene(final JScrollPane scrollPane, final ControlFlowGraph cfg) { - addChild(clusterLayer); - addChild(mainLayer); - addChild(interractionLayer); - addChild(connectionLayer); - this.scrollPane = scrollPane; - this.loadModel(new CfgEnv(cfg)); - this.getInputBindings().setZoomActionModifiers(0); - this.getActions().addAction(ActionFactory.createMouseCenteredZoomAction(1.1)); - this.getActions().addAction(ActionFactory.createPanAction()); - this.getActions().addAction(ActionFactory.createRectangularSelectAction( - this.createSelectDecorator(this), - interractionLayer, - this.createRectangularSelectProvider())); - this.getActions().addAction(this.contextPopupAction); - this.addSceneListener(createSceneListener(this)); - this.validate(); - - getPreferences().addPreferenceChangeListener(preferenceChangeListener); - this.loadDefaults(); - } - - private void loadModel(CfgEnv cfgenv) { - this.env = cfgenv; - for (CfgNode n : env.getNodes()) { - addNode(n); - } - for (CfgEdge e : env.getEdges()) { - addEdge(e); - setEdgeSource(e, e.getSourceNode()); - setEdgeTarget(e, e.getTargetNode()); - } - this.stackLoops(cfgenv.getLoopMap()); - this.autoHideEdges(); - } - - public void loadDefaults() { - CfgPreferences prefs = CfgPreferences.getInstance(); - this.setBackground(prefs.getBackgroundColor()); - setUseBezierRouter(getPreferences().getBoolean(PREFERENCE_ROUTER, true)); - setLoopWidgets(getPreferences().getBoolean(PREFERENCE_LOOP_CLUSTER, true)); - setSceneLayout(getPreferences().getInt(PREFERENCE_LAYOUT, CfgEditorContext.LAYOUT_HIERARCHICALNODELAYOUT)); - } - - //sets the parent Widget of all LoopClusterWidgets - private void stackLoops(Map map) { - this.clusterLayer.removeChildren(); - - Set cache = new HashSet<>(); - for (LoopInfo info : map.values()) { - if (cache.contains(info)) { - continue; - } - LoopClusterWidget widget = this.loopidx2clusterwidget.get(info.getLoopIndex()); - LoopInfo parent = info.getParent(); - while (parent != null) { - LoopClusterWidget parentWidget = this.loopidx2clusterwidget.get(parent.getLoopIndex()); - assert parentWidget != null; - if (widget.getParentWidget() != null) { - widget.removeFromParent(); - } - parentWidget.addChild(widget); - widget = parentWidget; - parent = parent.getParent(); - } - widget.removeFromParent(); - this.clusterLayer.addChild(widget);//parent == null => parent is clusterlayer - } - } - - //hide in|output edges - private void autoHideEdges() { - for (CfgNode n : this.getNodes()) { - int fanin = n.getInputEdges().length; - int fanout = n.getOutputEdges().length; - if (fanin > CfgEditorContext.MAX_AUTOEDGESVISIBLE) { - assert (inputSwitches.containsKey(n)); - if (this.inputSwitches.containsKey(n)) { - EdgeSwitchWidget esw = this.inputSwitches.get(n); - esw.changeEdgeVisibility(false); - } - } - if (fanout > CfgEditorContext.MAX_AUTOEDGESVISIBLE) { - if (this.outputSwitches.containsKey(n)) { - EdgeSwitchWidget esw = this.outputSwitches.get(n); - esw.changeEdgeVisibility(false); - } - } - } - - } - - //apply current cfggraphscene layout - public void applyLayout() { - this.sceneLayout.invokeLayoutImmediately(); - } - - //returns a Set with the currently selected Nodes - public Set getSelectedNodes() { - return Collections.unmodifiableSet(selectedNodes); - } - - public Map getLoopidx2clusterwidget() { - return loopidx2clusterwidget; - } - - /** - * Sets the color of the currently selected Nodes If the supplied color is null the default color will be used - */ - public void setSelectedNodesColor(Color color) { - if (color == null) { //set default color - CfgPreferences prefs = CfgPreferences.getInstance(); - boolean customized = false; - for (CfgNode n : this.selectedNodes) { - color = null; - color = prefs.getFlagsSetting().getColor(n.getBasicBlock().getFlags()); - customized = (color != null); - NodeWidget nw = (NodeWidget) this.findWidget(n); - nw.setNodeColor((customized) ? color : prefs.getNodeColor(), customized); - } - } else { - for (CfgNode n : this.selectedNodes) { - NodeWidget nw = (NodeWidget) this.findWidget(n); - nw.setNodeColor(color, true); - } - } - this.validate(); - } - - public void setSelectedEdgesVisibility(boolean visible) { - for (CfgNode n : this.selectedNodes) { - EdgeSwitchWidget in = this.inputSwitches.get(n); - EdgeSwitchWidget out = this.outputSwitches.get(n); - if (in != null) { - in.changeEdgeVisibility(visible); - } - if (out != null) { - out.changeEdgeVisibility(visible); - } - } - this.validate(); - } - - public EdgeSwitchWidget getInputSwitch(CfgNode n) { - return this.inputSwitches.get(n); - } - - public EdgeSwitchWidget getOutputSwitch(CfgNode n) { - return this.outputSwitches.get(n); - } - - public CfgEnv getCfgEnv() { - return env; - } - - public boolean isLoopClusterVisible() { - return loopClustersVisible; - } - - public void setLoopWidgets(boolean visible) { - for (Widget w : this.loopidx2clusterwidget.values()) { - w.setVisible(visible); - w.revalidate(); - } - this.loopClustersVisible = visible; - this.validate(); - getPreferences().putBoolean(PREFERENCE_LOOP_CLUSTER, visible); - } - - private void setUseBezierRouter(boolean value) { - Router router; - if (value) { - router = new PolylineRouterV2(new WidgetCollisionCollector() { - @Override - public void collectCollisions(List collisions) { - collisions.addAll(getNodeWidgets()); - } - }); - } else { - router = RouterFactory.createDirectRouter(); - } - - for (CfgEdge e : this.getEdges()) { - EdgeWidget ew = (EdgeWidget) this.findWidget(e); - ew.setRouter(router); - } - this.validate(); - getPreferences().putBoolean(PREFERENCE_ROUTER, value); - } - - public Collection getNodeWidgets() { - if (nodeWidgets != null && nodeWidgets.size() == this.getNodes().size()) { - return nodeWidgets; - } - - List widgets = new ArrayList<>(); - for (CfgNode n : this.getNodes()) { - NodeWidget w = (NodeWidget) this.findWidget(n); - widgets.add(w); - } - - nodeWidgets = Collections.unmodifiableList(widgets); - return widgets; - } - - public void setSceneLayout(int newLayout) { - - GraphLayout graphLayout = null; - - switch (newLayout) { - case CfgEditorContext.LAYOUT_HIERARCHICALNODELAYOUT: - graphLayout = new HierarchicalNodeLayout(this); - break; - - case CfgEditorContext.LAYOUT_HIERARCHICALCOMPOUNDLAYOUT: - graphLayout = new HierarchicalCompoundLayout(this); - break; - } - - this.currentLayout = newLayout; - if (graphLayout != null) { - this.sceneLayout = LayoutFactory.createSceneGraphLayout(this, graphLayout); - } - - getPreferences().putInt(PREFERENCE_LAYOUT, newLayout); - sceneLayout.invokeLayoutImmediately(); - } - - @Override - protected void attachEdgeSourceAnchor(CfgEdge edge, CfgNode oldSourceNode, CfgNode sourceNode) { - Anchor sourceAnchor; - EdgeWidget edgeWidget = (EdgeWidget) findWidget(edge); - Widget sourceWidget = findWidget(sourceNode); - - if (edge.isSymmetric()) { - sourceAnchor = new SymmetricAnchor(sourceWidget, true, true); - } else { - sourceAnchor = AnchorFactory.createRectangularAnchor(sourceWidget); - } - edgeWidget.setSourceAnchor(sourceAnchor); - } - - @Override - protected void attachEdgeTargetAnchor(CfgEdge edge, CfgNode oldtarget, CfgNode targetNode) { - Anchor targetAnchor; - ConnectionWidget edgeWidget = (ConnectionWidget) findWidget(edge); - Widget targetWidget = findWidget(targetNode); - - if (edge.isSymmetric()) { - targetAnchor = new SymmetricAnchor(targetWidget, true, false); - } else { - targetAnchor = AnchorFactory.createRectangularAnchor(targetWidget); - } - edgeWidget.setTargetAnchor(targetAnchor); - } - - @Override - protected Widget attachEdgeWidget(CfgEdge edge) { - EdgeWidget widget = new EdgeWidget(this, edge); - connectionLayer.addChild(widget); - attachSourceSwitchWidget(edge); - attachTargetSwitchWidget(edge); - return widget; - } - - @Override - protected Widget attachNodeWidget(CfgNode node) { - this.nodeWidgets = null; - - NodeWidget nw = new NodeWidget(this, node); - WidgetAction.Chain actions = nw.getActions(); - actions.addAction(this.contextPopupAction); - actions.addAction(this.moveAction); - actions.addAction(this.createObjectHoverAction()); - - if (node.isLoopMember()) { - LoopClusterWidget loopWidget = this.attachLoopMember(node); - loopWidget.addMember(nw); - } - mainLayer.addChild(nw); - return nw; - } - - private LoopClusterWidget attachLoopMember(CfgNode node) { - LoopClusterWidget lw = this.loopidx2clusterwidget.get(node.getLoopIndex()); - if (lw == null) { - lw = new LoopClusterWidget(this, node.getLoopDepth(), node.getLoopIndex()); - this.loopidx2clusterwidget.put(node.getLoopIndex(), lw); - this.clusterLayer.addChild(lw); - } - return lw; - } - - private boolean detachLoopMember(CfgNode node, NodeWidget nodeWidget) { - LoopClusterWidget rm = this.loopidx2clusterwidget.get(node.getLoopIndex()); - if (rm == null) { - return false;//not added - } - if (rm.removeMember(nodeWidget)) { - if (rm.getMembers().isEmpty()) { - this.loopidx2clusterwidget.remove(rm.getLoopIndex()); - List childs = new ArrayList<>(rm.getChildren()); - for (Widget w : childs) {//append stacked loopwidgets - w.removeFromParent(); - rm.getParentWidget().addChild(w); - } - rm.removeFromParent(); - } - return true; - } - return false; - } - - //this function is not invoked by any class of the module - //however to ensure that the edge switches are treatet corretly - //when a future version removes nodes it was implemented too. - @Override - protected void detachNodeWidget(CfgNode node, Widget nodeWidget) { - if (node.isLoopMember() && nodeWidget instanceof NodeWidget) { - this.detachLoopMember(node, (NodeWidget) nodeWidget); - } - super.detachNodeWidget(node, nodeWidget); - assert nodeWidget.getParentWidget() == null; - if (this.inputSwitches.containsKey(node)) { - EdgeSwitchWidget esw = this.inputSwitches.remove(node); - this.connectionLayer.removeChild(esw); - } - if (this.outputSwitches.containsKey(node)) { - EdgeSwitchWidget esw = this.outputSwitches.remove(node); - this.connectionLayer.removeChild(esw); - } - } - - protected EdgeSwitchWidget attachSourceSwitchWidget(CfgEdge e) { - CfgNode sourceNode = e.getSourceNode(); - NodeWidget sourceWidget = (NodeWidget) this.findWidget(sourceNode); - EdgeSwitchWidget out = outputSwitches.get(sourceNode); - if (out == null) { - out = new EdgeSwitchWidget(this, sourceWidget, true); - this.connectionLayer.addChild(out); - outputSwitches.put(sourceNode, out); - } - return out; - } - - protected EdgeSwitchWidget attachTargetSwitchWidget(CfgEdge e) { - CfgNode targetNode = e.getTargetNode(); - NodeWidget targetWidget = (NodeWidget) this.findWidget(targetNode); - EdgeSwitchWidget in = inputSwitches.get(targetNode); - if (in == null) { - in = new EdgeSwitchWidget(this, targetWidget, false); - this.connectionLayer.addChild(in); - inputSwitches.put(targetNode, in); - } - return in; - } - - //resets the selection state of all NodeWidgets - private void cleanNodeSelection() { - if (!this.selectedNodes.isEmpty()) { - this.userSelectionSuggested(Collections.emptySet(), false); - this.selectedNodes = Collections.emptySet(); - this.validate(); - } - } - - //sets the scene & global node selection - public void setNodeSelection(Set newSelection) { - this.setSceneSelection(newSelection); - this.updateGlobalSelection(); - } - - //sets the scene selection - private void setSceneSelection(Set newSelection) { - if (newSelection.equals(selectedNodes)) { - return; - } - - this.selectedNodes = newSelection; - - Set selectedObjects = new HashSet<>(); - - for (CfgNode n : newSelection) { - selectedObjects.addAll(this.findNodeEdges(n, true, true)); - } - selectedObjects.addAll(newSelection); - - //if the selection gets updated from a change in the block view - //the scene will be centered - if (selectionUpdating) { - this.centerSelection(); - } - - this.userSelectionSuggested(selectedObjects, false); - this.validate(); - } - - //updates selection of Block View - public void updateGlobalSelection() { - // TODO(tw): Add selection management. -// Selection selection = SelectionManager.getDefault().getCurSelection(); -// ArrayList newBlocks = new ArrayList(); -// for (CfgNode n : this.selectedNodes) { -// newBlocks.add(n.getBasicBlock()); -// } -// BasicBlock[] curBlocks = newBlocks.toArray(new BasicBlock[newBlocks.size()]); -// selection.put(curBlocks); - } - private boolean selectionUpdating = false; - - //change of blockview selection - public void stateChanged(ChangeEvent event) { - if (selectionUpdating) { - return; - } - - selectionUpdating = true; - - Object source = event.getSource(); -// if(source instanceof Selection){ -// Selection selection=(Selection) source; -// Set newSelection = new HashSet(); -// BasicBlock[] newBlocks = selection.get(BasicBlock[].class); -// if (newBlocks != null) { -// for(BasicBlock b : newBlocks){ -// for(CfgNode n : this.getNodes()){ -// if(n.getBasicBlock() == b) newSelection.add(n); -// } -// } -// this.setSceneSelection(newSelection); -// } -// } - selectionUpdating = false; - // TODO(tw): Add selection management. - } - - //centers the viewport on the currently selected nodewidgets - private void centerSelection() { - Point sceneCenter = null; - Collection nodes = this.selectedNodes; - if (nodes.size() == 0) { - nodes = this.getNodes(); - } - - for (CfgNode n : nodes) { - if (sceneCenter == null) { - sceneCenter = this.findWidget(n).getLocation(); - continue; - } - Point location = this.findWidget(n).getLocation(); - sceneCenter.x = (location.x + sceneCenter.x) / 2; - sceneCenter.y = (location.y + sceneCenter.y) / 2; - } - - JComponent view = this.getView(); - if (view != null) { - Rectangle viewBounds = view.getVisibleRect(); - - Point viewCenter = this.convertSceneToView(sceneCenter); - - view.scrollRectToVisible(new Rectangle( - viewCenter.x - viewBounds.width / 2, - viewCenter.y - viewBounds.height / 2, - viewBounds.width, - viewBounds.height)); - } - } - - public void zoomScene() { - JScrollPane pane = scrollPane; - Rectangle prefBounds = this.getPreferredBounds(); - Dimension viewDim = pane.getViewportBorderBounds().getSize(); - - double realwidth = (double) prefBounds.width * this.getZoomFactor(); - double realheight = (double) prefBounds.height * this.getZoomFactor(); - - double zoomX = (double) viewDim.width / realwidth; - double zoomY = (double) viewDim.height / realheight; - double zoomFactor = Math.min(zoomX, zoomY); - this.setZoomFactor(zoomFactor * 0.9); - } - - //Enables Antialiasing - @Override - public void paintChildren() { - Object anti = getGraphics().getRenderingHint(RenderingHints.KEY_ANTIALIASING); - Object textAnti = getGraphics().getRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING); - - getGraphics().setRenderingHint( - RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - getGraphics().setRenderingHint( - RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); - - super.paintChildren(); - - getGraphics().setRenderingHint(RenderingHints.KEY_ANTIALIASING, anti); - getGraphics().setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, textAnti); - } - - //select provider for node selection - private RectangularSelectProvider createRectangularSelectProvider() { - return new RectangularSelectProvider() { - - public void performSelection(Rectangle rectangle) { - HashSet set = new HashSet<>(); - - //change to a rectangle with (x,offsetY) at the top left - if (rectangle.width < 0) { - rectangle.x = rectangle.x + rectangle.width; - rectangle.width *= -1; - } - if (rectangle.height < 0) { - rectangle.y = rectangle.y + rectangle.height; - rectangle.height *= -1; - } - - for (NodeWidget n : getNodeWidgets()) { - Point p = n.getLocation(); - if (p != null && rectangle.contains(p)) { - set.add(n.getNodeModel()); - } - } - setNodeSelection(set); - } - }; - } - - //select decorator for node selection - private RectangularSelectDecorator createSelectDecorator(final CfgScene scene) { - return new RectangularSelectDecorator() { - - public Widget createSelectionWidget() { - scene.cleanNodeSelection();//unselected all nodes - scene.revalidate(); - return new SelectionWidget(getScene()); - } - }; - } - - private MoveProvider createMoveProvider() { - return new MoveProvider() { - - private HashMap originals = new HashMap<>(); - private Point original = null; - - public void movementStarted(Widget widget) { - originals.clear(); - NodeWidget nw = (NodeWidget) widget; - if (selectedNodes.contains(nw.getNodeModel())) {//move current selection - for (CfgNode n : selectedNodes) { - Widget w = findWidget(n); - originals.put(w, w.getLocation()); - } - } else {//a newly-selected node will be moved - CfgNode n = nw.getNodeModel(); - HashSet selectedNode = new HashSet<>(1); - selectedNode.add(n); - setNodeSelection(selectedNode); - originals.put(widget, widget.getPreferredLocation()); - widget.revalidate(); - validate(); - - } - } - - public void movementFinished(Widget widget) { - NodeWidget nw = (NodeWidget) widget; - if (selectedNodes.contains(nw.getNodeModel())) { - return;//to be able to move the current selection - } - - HashSet selectedNode = new HashSet<>(1); - selectedNode.add(nw.getNodeModel()); - setNodeSelection(selectedNode); - originals.clear(); - original = null; - - } - - public Point getOriginalLocation(Widget widget) { - if (original == null) { - original = widget.getLocation(); - } - - return original; - } - //todo : find a cache algorithm which only routes edges - //which are intersected by bounds of the moved rectangle - - public void setNewLocation(Widget widget, Point location) { - Point org = getOriginalLocation(widget); - int dx = location.x - org.x; - int dy = location.y - org.y; - for (Map.Entry entry : originals.entrySet()) { - Point point = entry.getValue(); - entry.getKey().setPreferredLocation(new Point(point.x + dx, point.y + dy)); - } - for (CfgEdge e : getEdges()) { - EdgeWidget ew = (EdgeWidget) findWidget(e); - if (ew.isVisible()) { - ew.reroute(); - } - } - } - }; - } - - private WidgetAction createContextMenuAction(final CfgScene scene) { - return ActionFactory.createPopupMenuAction(new PopupMenuProvider() { - - public JPopupMenu getPopupMenu(Widget widget, Point point) { - JPopupMenu menu = new JPopupMenu(); - NodeWidget nw = null; - if (widget instanceof NodeWidget) { - nw = (NodeWidget) widget; - if (!selectedNodes.contains(nw.getNodeModel())) { - HashSet selectedNode = new HashSet<>(1); - selectedNode.add(nw.getNodeModel()); - setNodeSelection(selectedNode); - } - } else if (scene.getSelectedNodes().size() == 1) { - nw = (NodeWidget) scene.findWidget(scene.getSelectedNodes().iterator().next()); - } - - if (nw != null) { - CfgNode node = nw.getNodeModel(); - ArrayList successors = new ArrayList<>(); - ArrayList predecessors = new ArrayList<>(); - for (CfgEdge e : node.getOutputEdges()) { - successors.add(e.getTargetNode()); - } - for (CfgEdge e : node.getInputEdges()) { - predecessors.add(e.getSourceNode()); - } - - if (predecessors.size() > 0) { - Collections.sort(predecessors, new NodeNameComparator()); - JMenu predmenu = new JMenu("Go to predecessor"); - for (CfgNode n : predecessors) { - GotoNodeAction action = new GotoNodeAction(n); - predmenu.add(action); - } - menu.add(predmenu); - } - if (successors.size() > 0) { - Collections.sort(successors, new NodeNameComparator()); - JMenu succmenu = new JMenu("Go to successor"); - for (CfgNode n : successors) { - GotoNodeAction action = new GotoNodeAction(n); - succmenu.add(action); - } - menu.add(succmenu); - } - if (successors.size() > 0 || predecessors.size() > 0) { - menu.addSeparator(); - } - } - - return menu; - } - }); - } - - @Override - public void zoomIn() { - this.setZoomFactor(this.getZoomFactor() * 1.1); - this.validate(); - } - - @Override - public void zoomOut() { - this.setZoomFactor(this.getZoomFactor() * 0.9); - this.validate(); - } - - @Override - public void showAll() { - this.zoomScene(); - this.validate(); - } - - private class NodeNameComparator implements Comparator { - - public int compare(CfgNode node1, CfgNode node2) { - String name1 = node1.getBasicBlock().getName().substring(1); - String name2 = node2.getBasicBlock().getName().substring(1); - Integer blocknum1 = Integer.parseInt(name1); - Integer blocknum2 = Integer.parseInt(name2); - return blocknum1.compareTo(blocknum2); - } - } - - private class GotoNodeAction extends AbstractAction { - - CfgNode node; - - GotoNodeAction(CfgNode node) { - super(node.getBasicBlock().getName()); - this.node = node; - } - - public void actionPerformed(ActionEvent e) { - Set nodes = new HashSet<>(1); - nodes.add(node); - setNodeSelection(nodes); - centerSelection(); - } - } - - private SceneListener createSceneListener(final CfgScene scene) { - return new SceneListener() { - - public void sceneRepaint() { - } - - public void sceneValidating() { - } - - public void sceneValidated() { - if (scene.isLoopClusterVisible()) { //update only if visible - for (LoopClusterWidget cw : getLoopidx2clusterwidget().values()) { - cw.updateClusterBounds(); - } - } - for (EdgeSwitchWidget esw : inputSwitches.values()) { - esw.updatePosition(); - } - - for (EdgeSwitchWidget esw : outputSwitches.values()) { - esw.updatePosition(); - } - } - }; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/EdgeSwitchWidget.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/EdgeSwitchWidget.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,290 +0,0 @@ -package at.ssw.visualizer.cfg.graph; - -import at.ssw.visualizer.cfg.model.CfgEdge; -import at.ssw.visualizer.cfg.model.CfgNode; -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.Polygon; -import java.awt.Rectangle; -import java.awt.geom.AffineTransform; -import java.util.ArrayList; -import java.util.Collection; -import org.netbeans.api.visual.action.ActionFactory; -import org.netbeans.api.visual.action.SelectProvider; -import org.netbeans.api.visual.action.TwoStateHoverProvider; -import org.netbeans.api.visual.action.WidgetAction; -import org.netbeans.api.visual.model.ObjectState; -import org.netbeans.api.visual.widget.Widget; - - -public class EdgeSwitchWidget extends Widget { - private final static Color color_enabled = Color.gray; - private final static Color color_hover = Color.lightGray; - private float width=1; - private float height=1; - private CfgScene scene; - private NodeWidget nodeWidget; - private boolean output; - private WidgetAction hoverAction; - private static final String TT_HIDE_EDGES = "Hide Edges"; - private static final String TT_SHOW_EDGES = "Show Edges"; - private static SelectProvider selectProvider = createSelectProvider(); - - - public EdgeSwitchWidget(final CfgScene scene, NodeWidget nodeWidget, boolean output) { - super(scene); - this.scene = scene; - this.output = output; - this.nodeWidget = nodeWidget; - - this.getActions().addAction(ActionFactory.createSelectAction(selectProvider)); - TwoStateHoverProvider ts = new TsHover(this); - WidgetAction wa = ActionFactory.createHoverAction(ts); - this.hoverAction = wa; - this.getActions().addAction(wa); - scene.getActions().addAction(wa); - this.setToolTipText(TT_HIDE_EDGES); - this.setForeground(color_enabled); - this.setState(ObjectState.createNormal()); - } - - - @Override - protected Rectangle calculateClientArea() { - if (this.nodeWidget.getBounds() == null) return new Rectangle(0, 0, 1, 1); - int hw = (int) (this.width / 2); - int hh = (int) (this.height /2); - - return new Rectangle(-hw, -hh, 2*hw, 2*hh); - } - - - public void updatePosition() { - if (this.nodeWidget.getBounds() != null) { - this.width = nodeWidget.getBounds().width*9; - this.width /=10; - this.height = nodeWidget.getBounds().height/4; - int offset=(int)(2 * (height / 3)); - - Rectangle bounds = nodeWidget.getBounds(); - Point location = nodeWidget.getLocation(); - - Point newLoc = new Point(); - newLoc.x = location.x; - - if(output) { - newLoc.y = +location.y + bounds.height/2+offset; - }else { - newLoc.y = location.y - bounds.height/2-offset; - } - this.setPreferredLocation(newLoc); - } - } - - private Collection getEdges(){ - Collection edges; - CfgNode node = nodeWidget.getNodeModel(); - if (output) { - edges = scene.findNodeEdges(node, true, false); - } else { - edges = scene.findNodeEdges(node, false, true); - } - return edges; - } - - //change visibility for all Edges - public void changeEdgeVisibility(boolean visible){ - Collection edges = this.getEdges(); - - for(CfgEdge e: edges) { - EdgeWidget ew = (EdgeWidget) scene.findWidget(e); - if(visible != ew.isEdgeVisible()){ - ew.setEdgeVisible(visible); - if(output){ - scene.getInputSwitch(e.getTargetNode()).updateStatus(); - } else { - scene.getOutputSwitch(e.getSourceNode()).updateStatus(); - } - } - } - if(visible) - this.setToolTipText(TT_HIDE_EDGES); - else - this.setToolTipText(TT_SHOW_EDGES); - - this.setForeground(color_enabled); - this.bringToBack(); - ObjectState os = this.getState(); - this.setState(os.deriveSelected(!visible)); - } - - /** - * Update the status of the switch to the current state of the edges - * usually needed when the opposit switch changes the state - */ - private void updateStatus(){ - Collection edges = this.getEdges(); - boolean hiddenFound=false; - for(CfgEdge e: edges) { - EdgeWidget ew = (EdgeWidget) scene.findWidget(e); - if(!ew.isVisible()) { - hiddenFound=true; - break; - } - } - ObjectState os = this.getState(); - if(os.isSelected() && !hiddenFound) { - this.setState(os.deriveSelected(false)); - setToolTipText(TT_HIDE_EDGES); - } else if (!os.isSelected() && hiddenFound) { - this.setState(os.deriveSelected(true)); - setToolTipText(TT_SHOW_EDGES); - } - this.revalidate(); - } - - - public void startPreview() { - ObjectState os = this.getState(); - - for(CfgEdge e : getEdges()) { - EdgeWidget ew = (EdgeWidget) scene.findWidget(e); - if(!os.isSelected() || !ew.isVisible()){ - ObjectState edgeState = ew.getState(); - ew.setState(edgeState.deriveHighlighted(true)); - } - } - } - - public void endPreview(){ - for(CfgEdge e : getEdges()) { - EdgeWidget ew = (EdgeWidget) scene.findWidget(e); - ObjectState os = ew.getState(); - ew.setState(os.deriveHighlighted(false)); - } - } - - /** - * shows or hides the edges of the switch - */ - public void switchEdges() { - endPreview(); - ObjectState os = this.getState(); - Collection edges = this.getEdges(); - ArrayList updates = new ArrayList<>(); - boolean visible=os.isSelected(); - this.setState(os.deriveSelected(!visible)); - for(CfgEdge e: edges) { - EdgeWidget ew = (EdgeWidget) scene.findWidget(e); - if(ew.isEdgeVisible() != visible){ - updates.add(e); - ew.setEdgeVisible(visible); - if(output){ - scene.getInputSwitch(e.getTargetNode()).updateStatus(); - } else { - scene.getOutputSwitch(e.getSourceNode()).updateStatus(); - } - } - } - if(visible) - this.setToolTipText(TT_HIDE_EDGES); - else - this.setToolTipText(TT_SHOW_EDGES); - - revalidate(); - } - - - - - private class TsHover implements TwoStateHoverProvider { - EdgeSwitchWidget tw; - - TsHover(EdgeSwitchWidget tw) { - this.tw = tw; - } - - public void unsetHovering(Widget w) { - w.setForeground(color_enabled); - ObjectState state = w.getState(); - w.setState(state.deriveWidgetHovered(false)); - w.bringToBack(); - endPreview(); - } - - public void setHovering(Widget w) { - ObjectState state = w.getState(); - w.setState(state.deriveWidgetHovered(true)); - w.setForeground(color_hover); - w.bringToFront(); - nodeWidget.bringToFront(); - startPreview(); - } - } - - @Override - public void paintWidget() { - ObjectState os = this.getState(); - if(!os.isHovered() && !os.isSelected()) return; //all previewEdges visible and not hovering, - //no need to paint the switch - float hw = width/2; - Polygon pol = new Polygon(); - pol.addPoint(0,(int) -height/2); - pol.addPoint((int)hw,(int) height/2); - pol.addPoint((int)-hw,(int) height/2); - Graphics2D gr = getGraphics(); - gr.setColor(this.getForeground()); - BasicStroke bs = new BasicStroke(2.0f, BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND); - gr.setStroke(bs); - AffineTransform previousTransform; - previousTransform = gr.getTransform (); - if(output) { - if(os.isSelected() ){//hidden - gr.scale(1.0, -1.0); - } - } else { //input switch - if(os.isHovered() && !os.isSelected()){ - gr.scale(1.0, -1.0); - } - } - gr.fillPolygon(pol); - gr.setTransform(previousTransform); - - } - - - - //the constructor adds the hover WidgetAction to the scene - //the action is removed from the scene when the object gets destroyed - @Override - protected void finalize() throws Throwable { - this.getScene().getActions().removeAction(hoverAction); - this.getActions().removeAction(hoverAction); - } - - @Override - public String toString(){ - return "EDGESWITCH("+this.nodeWidget.getNodeModel().toString()+")"; - } - - private static SelectProvider createSelectProvider() { - return new SelectProvider(){ - public boolean isAimingAllowed(Widget arg0, Point arg1, boolean arg2) { - return false; - } - - public boolean isSelectionAllowed(Widget arg0, Point arg1, boolean arg2) { - return true; - } - - public void select(Widget w, Point arg1, boolean arg2) { - if(w instanceof EdgeSwitchWidget){ - EdgeSwitchWidget tw = (EdgeSwitchWidget) w; - tw.switchEdges(); - } - } - }; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/EdgeWidget.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/EdgeWidget.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -package at.ssw.visualizer.cfg.graph; - -import at.ssw.visualizer.cfg.model.CfgEdge; -import at.ssw.visualizer.cfg.preferences.CfgPreferences; -import at.ssw.visualizer.cfg.visual.BezierWidget; -import at.ssw.visualizer.cfg.visual.SplineConnectionWidget; -import org.netbeans.api.visual.anchor.AnchorShapeFactory; -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Stroke; -import org.netbeans.api.visual.anchor.AnchorShape; -import org.netbeans.api.visual.model.ObjectState; - -//public class EdgeWidget extends BezierWidget { -public class EdgeWidget extends SplineConnectionWidget { - - private boolean visible=true;//to store the visible state when entering the preview - protected static final Stroke selectedStroke = new BasicStroke(3.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); - protected static final Stroke defaultStroke = new BasicStroke(1.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); - protected static final Stroke previewStroke = new BasicStroke( - 0.5f, // Width - BasicStroke.CAP_SQUARE, // End cap - BasicStroke.JOIN_MITER, // Join style - 10.0f, // Miter limit - new float[] {5.0f, 5.0f}, // Dash pattern - 0.0f); - - - - public EdgeWidget(CfgScene scene, CfgEdge edge) { - super(scene); - Color lineColor; - CfgPreferences prefs = CfgPreferences.getInstance(); - - if(edge.isBackEdge()) - lineColor = prefs.getBackedgeColor(); - else if (edge.isXhandler()) - lineColor = prefs.getExceptionEdgeColor(); - else - lineColor = prefs.getEdgeColor(); - - setLineColor(lineColor); - AnchorShape as; - if(edge.isReflexive())//small Arrow - as = AnchorShapeFactory.createTriangleAnchorShape(6, true, false, 5); - else - as =AnchorShapeFactory.createTriangleAnchorShape(10, true, false, 9); - - setTargetAnchorShape(as); - setToolTipText(edge.toString()); - } - - public CfgEdge getEdgeModel() { - CfgScene scene = (CfgScene) this.getScene(); - return (CfgEdge) scene.findObject(this); - } - - public void setEdgeVisible(boolean visible) { - this.visible=visible; - this.setVisible(visible); - this.reroute(); - this.revalidate(); - } - - - public boolean isEdgeVisible(){ - return visible; - } - - - @Override - public void notifyStateChanged(ObjectState oldState, ObjectState newState) { - setForeground (getLineColor()); - - if(newState.isHighlighted() && !oldState.isHighlighted()){ - this.setStroke(previewStroke); - this.setVisible(true); - } else { - if(newState.isSelected()){ - this.setStroke(selectedStroke); - } else { - this.setStroke(defaultStroke); - } - if(this.isEdgeVisible()){ - this.setVisible(true); - } else { - this.setVisible(false); - } - } - } - - - @Override - public String toString(){ - return "EdgeWidget[" + getEdgeModel().toString() + "]"; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/LoopClusterWidget.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/LoopClusterWidget.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -package at.ssw.visualizer.cfg.graph; - -import at.ssw.visualizer.cfg.model.LoopInfo; -import java.awt.Color; -import java.awt.Rectangle; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; -import org.netbeans.api.visual.action.ActionFactory; -import org.netbeans.api.visual.action.EditProvider; -import org.netbeans.api.visual.border.BorderFactory; -import org.netbeans.api.visual.widget.Widget; - -public class LoopClusterWidget extends Widget implements Comparable { - private static final int INSET = 10;//min space between node members and cluster border - private static final int DASHSIZE = 10; - private Color color = Color.BLUE; - private int loopIndex; - private int loopDepth; - private CfgScene cfgscene; - private ArrayList members = new ArrayList<>(); - - public LoopClusterWidget(CfgScene scene, int loopdepth, final int loopindex) { - super(scene); - this.cfgscene = scene; - this.loopIndex = loopindex; - this.loopDepth = loopdepth; - this.setBorder(BorderFactory.createDashedBorder(color, DASHSIZE, DASHSIZE/2, true)); - this.getActions().addAction(ActionFactory.createEditAction( new EditProvider() { //double click action - public void edit(Widget w) { - if(w instanceof LoopClusterWidget){ - for(LoopInfo info : cfgscene.getCfgEnv().getLoopMap().values()){ - if(info.getLoopIndex() == loopindex){ - cfgscene.setNodeSelection(info.getMembers()); - break; - } - } - } - } - })); - - } - - public List getMembers() { - return members; - } - - public int getLoopIndex() { - return loopIndex; - } - - public void addMember(NodeWidget nw) { - assert(!this.members.contains(nw)); - members.add(nw); - } - - public boolean removeMember(NodeWidget nw) { - if(this.members.contains(nw)){ - members.remove(nw); - return true; - } - return false; - } - - public void setrandomColor(){ - if(this.loopDepth == 0 ) return; - Random rand = new Random(); - Color randColor = Color.getHSBColor(rand.nextFloat()%360,0.1f,1.0f); - this.setBackground(randColor); - } - - //updates the bounds of the widget, - //and revalidates the widget if a membernode changed the scene position - public void updateClusterBounds(){ - Rectangle boundRect=null; - - for(NodeWidget nw : this.members){ - if(boundRect==null){ - boundRect = nw.convertLocalToScene(nw.getBounds()); - } else { - boundRect = boundRect.union(nw.convertLocalToScene(nw.getBounds())); - } - } - if(boundRect==null) return; - for(Widget w : this.getChildren()) { - if(w instanceof LoopClusterWidget) { - LoopClusterWidget lc = (LoopClusterWidget)w; - lc.updateClusterBounds(); - boundRect = boundRect.union(w.convertLocalToScene(w.getBounds())); - } - } - - boundRect.grow(INSET, INSET); - this.setPreferredBounds(boundRect); - } - - - public int compareTo(LoopClusterWidget o) { - return new Integer(this.loopDepth).compareTo(o.loopDepth); - } - - - @Override - public String toString(){ - return "LoopCluster: [DEPTH "+this.loopDepth+ "] [INDEX "+this.loopIndex+"]"; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/NodeWidget.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/NodeWidget.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,153 +0,0 @@ -package at.ssw.visualizer.cfg.graph; - -import at.ssw.visualizer.cfg.model.CfgNode; -import at.ssw.visualizer.cfg.preferences.CfgPreferences; -import java.awt.AlphaComposite; -import java.awt.Color; -import java.awt.Composite; -import java.awt.Font; -import java.awt.Graphics2D; -import java.awt.Insets; -import java.awt.Rectangle; -import java.awt.font.FontRenderContext; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.awt.geom.RoundRectangle2D; -import org.netbeans.api.visual.border.BorderFactory; -import org.netbeans.api.visual.model.ObjectState; -import org.netbeans.api.visual.widget.Widget; - - -public class NodeWidget extends Widget { - - - //basic block node dimension - private final int halfheight=12; - private final int halfwidth=17; - - private final int height=halfheight*2+1; - private final int width=halfwidth*2+1; - private final int arcHeight=(halfheight/4)*3; - private final int arcWidth = arcHeight; - private final int FONT_MAXSIZE=18; - - private int borderWidth; - private boolean nodeColorCustomized; - private String text; - private Rectangle2D fontRect; - private Color nodeColor; - - protected static final Color HOVER_BACKGROUND = new Color(0xEEEEEE); - protected static final Color HOVER_FOREGROUND = new Color(0xCDCDCD); - - public NodeWidget(CfgScene scene, CfgNode nodeModel ){ - super(scene); - this.setToolTipText("" + nodeModel.getDescription().replaceAll("\n", "
") + ""); - this.text = nodeModel.getBasicBlock().getName(); - this.borderWidth = nodeModel.getLoopDepth()+1; - this.setBorder(BorderFactory.createRoundedBorder(arcWidth+borderWidth, arcHeight+borderWidth, borderWidth, borderWidth, Color.BLACK, Color.BLACK)); - CfgPreferences prefs = CfgPreferences.getInstance(); - Color color = prefs.getFlagsSetting().getColor(nodeModel.getBasicBlock().getFlags()); - this.nodeColorCustomized = (color!=null); - this.nodeColor = (nodeColorCustomized) ? color : prefs.getNodeColor(); - this.adjustFont(null); - } - - public void setBorderColor(Color color){ - this.setBorder(BorderFactory.createRoundedBorder(arcWidth+borderWidth, arcHeight+borderWidth, borderWidth, borderWidth, color, color)); - } - - public boolean isNodeColorCustomized() { - return nodeColorCustomized; - } - - //sets a customColor node color - public void setNodeColor(Color color, boolean customColor) { - this.nodeColorCustomized=customColor; - this.nodeColor=color; - this.revalidate(); - } - - public Color getNodeColor() { - return this.nodeColor; - } - - public CfgNode getNodeModel() { - CfgScene scene = (CfgScene) this.getScene(); - return (CfgNode) scene.findObject(this); - } - - - @Override - public void notifyStateChanged(ObjectState oldState, ObjectState newState) { - if(!oldState.equals(newState)) - this.revalidate(); - if(!oldState.isSelected() && newState.isSelected()) - this.bringToFront(); - } - - @Override - protected Rectangle calculateClientArea() { - return new Rectangle(-(halfwidth+1), -(1+halfheight), width+1, height+1);//add border - } - - public void adjustFont(Font font){ - if(font==null) - font = CfgPreferences.getInstance().getTextFont(); - if(font.getSize()>FONT_MAXSIZE){ - font = new Font(font.getFamily(), font.getStyle(), FONT_MAXSIZE); - } - int size=font.getSize(); - int fontStyle = font.getStyle(); - String fontName = font.getFamily(); - FontRenderContext frc = new FontRenderContext(new AffineTransform(), false, false); - Rectangle2D bounds = font.getStringBounds(text, frc); - while(size > 1 && bounds.getWidth() > width) { - font = new Font(fontName, fontStyle, --size); - bounds = font.getStringBounds(text, frc); - } - this.fontRect=bounds; - this.setFont(font); - } - - @Override - protected void paintWidget() { - Graphics2D gr = getGraphics(); - gr.setColor(nodeColor); - Insets borderInsets = this.getBorder().getInsets(); - RoundRectangle2D.Float innerRect = new RoundRectangle2D.Float(-(halfwidth+1), -(halfheight+1), width+1, height+1,arcWidth-1, arcHeight-1); - gr.fill(innerRect); - gr.setColor(getForeground()); - gr.setFont(getFont()); - float textX = (float)( - fontRect.getCenterX()); - float textY = (float)( - fontRect.getCenterY()); - gr.drawString(text, textX, textY); - - RoundRectangle2D.Float outerRect = new RoundRectangle2D.Float(-(halfwidth+borderInsets.left + 1), -(halfheight+borderInsets.top + 1), - width+borderInsets.left + borderInsets.right + 1, height + borderInsets.top + borderInsets.bottom + 1, - arcWidth + borderWidth, arcHeight + borderWidth); - - ObjectState os =this.getState(); - if(os.isSelected()){ - Composite composite = gr.getComposite(); - gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f)); - gr.setColor(CfgPreferences.getInstance().getSelectionColorForeground()); - gr.fill(outerRect); - gr.setColor(CfgPreferences.getInstance().getSelectionColorBackground()); - gr.setComposite(composite); - } - if(os.isHovered()){ - Composite composite = gr.getComposite(); - gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f)); - gr.setColor(HOVER_FOREGROUND); - gr.fill(outerRect); - gr.setColor(HOVER_BACKGROUND); - gr.setComposite(composite); - } - } - - @Override - public String toString() { - return "NodeWidget[" + getNodeModel().getBasicBlock().getName() + "]"; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/SelectionWidget.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/SelectionWidget.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -package at.ssw.visualizer.cfg.graph; - -import at.ssw.visualizer.cfg.preferences.CfgPreferences; -import java.awt.AlphaComposite; -import java.awt.Composite; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import org.netbeans.api.visual.widget.Scene; -import org.netbeans.api.visual.widget.Widget; - - -public class SelectionWidget extends Widget { - public SelectionWidget(Scene scene) { - super(scene); - } - - public static void renderSelectedRect(Graphics2D gr, Rectangle rect) { - if (rect == null) { - return; - } - gr.setColor(CfgPreferences.getInstance().getSelectionColorBackground()); - gr.fillRect(rect.x, rect.y, rect.width, rect.height); - gr.setColor(CfgPreferences.getInstance().getSelectionColorForeground()); - } - - public void renderSelectionRectangle(Graphics2D gr, Rectangle selectionRectangle) { - Composite composite = gr.getComposite(); - gr.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f)); - - renderSelectedRect(gr, selectionRectangle); - gr.setComposite(composite); - } - - @Override - public void paintWidget(){ - this.renderSelectionRectangle(this.getGraphics(), this.getBounds()); - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/SymmetricAnchor.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/SymmetricAnchor.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,157 +0,0 @@ -package at.ssw.visualizer.cfg.graph; - -import org.netbeans.api.visual.widget.Widget; -import org.netbeans.api.visual.anchor.Anchor; -import java.awt.*; - - -/** - * This Anchor can be used with symmetric edges to create parallel Edges. - * Two Directed Edges are symmetric if they are connecting the same Nodes in different directions. - * e.g. Nodes (1, 2) Edges(a , b) with (1)-a->(2) , (2)-b->(1) - * Start-/End positions are calculated with a fixed offset to prevent edges from overlapping. - * If the edges are drawn as straight lines they will appear as parallel edges. - */ - -public final class SymmetricAnchor extends Anchor { - - private final static int OFFSET = 10; - private boolean includeBorders; - private int offx; - private int offy; - - public SymmetricAnchor (Widget widget, boolean includeBorders, boolean source) { - super (widget); - this.includeBorders = includeBorders; - if (source) { - offx = OFFSET; - offy = OFFSET; - } - else { - offx = -OFFSET; - offy = -OFFSET; - } - } - - public Result compute (Entry entry) { - Point relatedLocation = //center of the widget - getRelatedSceneLocation (); - Point oppositeLocation = //center of the widget - getOppositeSceneLocation (entry); - - Widget widget = getRelatedWidget (); - Rectangle bounds = widget.getBounds (); - if (! includeBorders) { - Insets insets = widget.getBorder ().getInsets (); - bounds.x += insets.left; - bounds.y += insets.top; - bounds.width -= insets.left + insets.right; - bounds.height -= insets.top + insets.bottom; - } - - bounds = widget.convertLocalToScene (bounds); - - if (bounds.isEmpty () || relatedLocation.equals (oppositeLocation)) - return new Anchor.Result (relatedLocation, Anchor.DIRECTION_ANY); - - float dx //distance x-axis - = oppositeLocation.x - relatedLocation.x; - float dy //distance y-axis - = oppositeLocation.y - relatedLocation.y; - - - float ddx - = Math.abs (dx) / (float) bounds.width; - float ddy = - Math.abs (dy) / (float) bounds.height; - - Anchor.Direction direction; - - - if (ddx >= ddy) { - if(dx >= 0.0f){ - direction = Direction.RIGHT; - relatedLocation.y -= offy; - } else { - direction = Direction.LEFT; - relatedLocation.y += offy; - } - } else { - if(dy >= 0.0f){ - direction = Direction.BOTTOM; - relatedLocation.x += offx; - } else { - direction = Direction.TOP; - relatedLocation.x -= offx; - } - } - - - float scale = 0.5f / Math.max (ddx, ddy); - - float ex = scale * dx; - float ey = scale * dy; - - Point point = new Point (Math.round (relatedLocation.x + ex), Math.round (relatedLocation.y + ey)); - - if(direction == Direction.RIGHT) { - int top = bounds.y;//-bounds.height;// left y of the widget - int bottom = bounds.y + bounds.height;// right y of the widget - if(point.y < top) {//above the widget - int cor = top-point.y; - point.x -= cor; - point.y += cor; - } else if ( point.y > bottom) { - int cor = point.y-bottom; - point.x -= cor; - point.y -= cor; - } - - } else if (direction == Direction.LEFT) { - int top = bounds.y;//-bounds.height;// left y of the widget - int bottom = bounds.y + bounds.height;// right y of the widget - - - - if(point.y < top) {//above the widget - int cor = top-point.y; - point.x += cor; - point.y += cor; - } else if ( point.y > bottom) { - int cor = bottom-point.y; - point.x -= cor; - point.y += cor; - } - - - } else if (direction == Direction.BOTTOM) { - int left = bounds.x;//-bounds.height;// left y of the widget - int right = bounds.x + bounds.width;// right y of the widget - if(point.x < left) {//above the widget - int cor = left-point.x; - point.x += cor; - point.y -= cor; - } else if ( point.x > right) { - int cor = point.x- right; - point.x -= cor; - point.y -= cor; - } - - } else if (direction == Direction.TOP) { - int left = bounds.x;//-bounds.height;// left y of the widget - int right = bounds.x + bounds.width;// right y of the widget - if(point.x < left) {//above the widget - int cor = left-point.x; - point.x += cor; - point.y += cor; - } else if ( point.x > right) { - int cor = point.x - right; - point.x -= cor; - point.y += cor; - } - - } - - return new Anchor.Result (point, direction); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/HierarchicalCompoundLayout.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/HierarchicalCompoundLayout.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -package at.ssw.visualizer.cfg.graph.layout; - -import at.ssw.visualizer.cfg.graph.CfgScene; -import at.ssw.visualizer.cfg.model.CfgEdge; -import at.ssw.visualizer.cfg.model.CfgNode; -import at.ssw.visualizer.cfg.model.LoopInfo; -import java.awt.Point; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import org.eclipse.draw2d.geometry.Insets; -import org.netbeans.api.visual.graph.layout.GraphLayout; -import org.netbeans.api.visual.graph.layout.UniversalGraph; -import org.eclipse.draw2d.graph.CompoundDirectedGraph; -import org.eclipse.draw2d.graph.CompoundDirectedGraphLayout; -import org.eclipse.draw2d.graph.Edge; -import org.eclipse.draw2d.graph.EdgeList; -import org.eclipse.draw2d.graph.Node; -import org.eclipse.draw2d.graph.NodeList; -import org.eclipse.draw2d.graph.Subgraph; -import org.netbeans.api.visual.widget.Widget; - -public class HierarchicalCompoundLayout extends GraphLayout { - - private static final int TOP_BORDER = 20; - private static final int LEFT_BORDER = 20; - private int PADDING = 20; - private static final int INSET = 20; - private CfgScene scene; - - public HierarchicalCompoundLayout(CfgScene scene){ - this.scene = scene; - } - - @Override - protected void performGraphLayout(UniversalGraph ug) { - CompoundDirectedGraph dg = new CompoundDirectedGraph(); - CompoundDirectedGraphLayout layout = new CompoundDirectedGraphLayout(); - NodeList nodeList = dg.nodes; - EdgeList edgeList = dg.edges; - - Map idx2graph = new HashMap<>(); - Subgraph base = new Subgraph(0); - idx2graph.put(0, base); - base.insets=getInsets(); - for(LoopInfo info : scene.getCfgEnv().getLoopMap().values()){ - Subgraph subg = new Subgraph(info.getLoopIndex()); - subg.insets=getInsets(); - idx2graph.put(info.getLoopIndex(), subg); - } - - for(CfgNode n : scene.getCfgEnv().getNodes() ) { - Widget nodeWidget = scene.findWidget(n); - Node node = new Node(n); - node.width=nodeWidget.getBounds().width; - node.height = nodeWidget.getBounds().height; - node.setPadding(new Insets(PADDING, PADDING, PADDING, PADDING)); - Subgraph subg = idx2graph.get(n.getLoopIndex()); - assert(subg != null); - node.setParent(subg); - subg.addMember(node); - nodeList.add(node); - - } - nodeList.addAll(idx2graph.values()); - for(LoopInfo info : scene.getCfgEnv().getLoopMap().values()){ - Subgraph subg = idx2graph.get(info.getLoopIndex()); - if(info.getParent() != null){ - Subgraph parentsubg = idx2graph.get(info.getParent().getLoopIndex()); - Edge edge = new Edge(parentsubg, subg); - parentsubg.addMember(subg); - subg.setParent(parentsubg); - edgeList.add(edge); - } - } - for(CfgEdge e : scene.getCfgEnv().getEdges() ) { - if(e.isBackEdge()) continue; - Edge edge = new Edge(e, nodeList.getNode(e.getSourceNode().getNodeIndex()), nodeList.getNode(e.getTargetNode().getNodeIndex())); - edgeList.add(edge); - } - layout.visit(dg); - - for(Object obj : dg.nodes){ - Node n = (Node) obj; - if(n.data instanceof CfgNode){ - CfgNode cfgNode = (CfgNode) n.data; - Point pos = new Point(n.x + LEFT_BORDER, n.y + TOP_BORDER); - Point scenepos = scene.convertLocalToScene(pos); - this.setResolvedNodeLocation(ug, cfgNode, scenepos); - } - } - } - - @Override - protected void performNodesLayout(UniversalGraph ug, Collection collection) { - } - - private Insets getInsets(){ - return new Insets(INSET, INSET, INSET, INSET); - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/HierarchicalNodeLayout.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/graph/layout/HierarchicalNodeLayout.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -package at.ssw.visualizer.cfg.graph.layout; - -import at.ssw.visualizer.cfg.graph.CfgScene; -import at.ssw.visualizer.cfg.model.CfgEdge; -import at.ssw.visualizer.cfg.model.CfgNode; -import java.awt.Point; -import java.util.Collection; -import org.netbeans.api.visual.graph.layout.GraphLayout; -import org.netbeans.api.visual.graph.layout.UniversalGraph; -import org.eclipse.draw2d.graph.DirectedGraph; -import org.eclipse.draw2d.graph.DirectedGraphLayout; -import org.eclipse.draw2d.graph.Edge; -import org.eclipse.draw2d.graph.EdgeList; -import org.eclipse.draw2d.graph.Node; -import org.eclipse.draw2d.graph.NodeList; -import org.netbeans.api.visual.widget.Widget; - - -public class HierarchicalNodeLayout extends GraphLayout { - - private static final int TOP_BORDER = 20; - private static final int LEFT_BORDER = 40; - - private CfgScene scene; - - public HierarchicalNodeLayout(CfgScene scene){ - this.scene = scene; - } - - @Override - protected void performGraphLayout(UniversalGraph ug) { - DirectedGraph dg = new DirectedGraph(); - DirectedGraphLayout layout = new DirectedGraphLayout(); - - NodeList nodeList = dg.nodes; - EdgeList edgeList = dg.edges; - - for(CfgNode n : scene.getCfgEnv().getNodes() ) { - Widget nodeWidget = scene.findWidget(n); - Node node = new Node(n); - node.width=nodeWidget.getBounds().width; - node.height = nodeWidget.getBounds().height; - nodeList.add(node); - } - - for(CfgEdge e : scene.getCfgEnv().getEdges() ) { - if(e.isBackEdge()) continue; - Edge edge = new Edge(e, nodeList.getNode(e.getSourceNode().getNodeIndex()), - nodeList.getNode(e.getTargetNode().getNodeIndex())); - edgeList.add(edge); - } - - layout.visit(dg); - - for(Object obj : dg.nodes){ - Node n = (Node) obj; - CfgNode cfgNode = (CfgNode) n.data; - Point pos = new Point(n.x + LEFT_BORDER , n.y + TOP_BORDER); - Point scenepos = scene.convertLocalToScene(pos); - setResolvedNodeLocation(ug, cfgNode, scenepos); - } - - } - - @Override - protected void performNodesLayout(UniversalGraph ug, Collection collection) { - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/Icons.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/Icons.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -package at.ssw.visualizer.cfg.icons; - -/** - * - * @author Christian Wimmer - */ -public class Icons { - private static final String PATH = "at/ssw/visualizer/cfg/icons/"; - - public static final String CFG = PATH + "cfg.gif"; - - public static final String ICON_ZOOMIN = PATH + "zoomin.gif"; - public static final String ICON_ZOOMOUT = PATH + "zoomout.gif"; - public static final String ICON_DEFAULT = PATH + "arrangebfs.gif"; - - private Icons() { - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/arrangebfs.gif Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/arrangebfs.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/arrangehier.gif Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/arrangehier.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/arrangeloop.gif Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/arrangeloop.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/autosize_selection.gif Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/autosize_selection.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/bezierrouter.gif Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/bezierrouter.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/cfg.gif Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/cfg.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/cfg32.gif Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/cfg32.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/cluster.gif Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/cluster.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/color.gif Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/color.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/combine.gif Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/combine.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/combine_disabled.gif Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/combine_disabled.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/disk.gif Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/disk.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/fanrouter.gif Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/fanrouter.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/hideedges.gif Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/hideedges.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/hideedges_disabled.gif Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/hideedges_disabled.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/manhattanrouter.gif Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/manhattanrouter.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/showedges.gif Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/showedges.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/showedges_disabled.gif Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/showedges_disabled.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/split.gif Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/split.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/split_disabled.gif Binary file visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/icons/split_disabled.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/layer.xml --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/layer.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgEdge.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgEdge.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -package at.ssw.visualizer.cfg.model; - -public interface CfgEdge { - public CfgNode getSourceNode(); - public CfgNode getTargetNode(); - public boolean isXhandler(); - public boolean isBackEdge(); - public boolean isSymmetric(); - public boolean isReflexive(); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgEdgeImpl.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgEdgeImpl.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -package at.ssw.visualizer.cfg.model; - -public class CfgEdgeImpl implements CfgEdge { - private CfgNodeImpl sourceNode; - private CfgNodeImpl targetNode; - private boolean symmetric; - private boolean backedge; - - public CfgEdgeImpl(CfgNodeImpl sourceNode, CfgNodeImpl targetNode) { - this.sourceNode = sourceNode; - this.targetNode = targetNode; - } - - public void setSymmetric(boolean symmetric){ - this.symmetric = symmetric; - } - - public void setBackEdge(boolean isBackedge){ - this.backedge = isBackedge; - } - - public CfgNode getSourceNode() { - return sourceNode; - } - - public CfgNode getTargetNode() { - return targetNode; - } - - public boolean isBackEdge() { - return this.backedge; - } - - public boolean isSymmetric() { - return symmetric; - } - - public boolean isReflexive() { - return sourceNode==targetNode; - } - - public boolean isXhandler() { - return sourceNode.getBasicBlock().getXhandlers().contains(targetNode.getBasicBlock()); - } - - @Override - public String toString(){ - return this.sourceNode.getBasicBlock().getName() + "->" + targetNode.getBasicBlock().getName(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgEnv.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgEnv.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,297 +0,0 @@ -package at.ssw.visualizer.cfg.model; - -import at.ssw.visualizer.model.cfg.BasicBlock; -import at.ssw.visualizer.model.cfg.ControlFlowGraph; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Queue; -import java.util.Set; - - -/** - * This is the container class for the data model, - * it prepares creates nodes and edges for the CfgScene - * from a ControlFlowGraph of the Compilation Model - */ -public class CfgEnv { - private ControlFlowGraph cfg; - private Map loopMap;//maps: LoopHeader --> LoopInfo - private CfgNodeImpl[] nodeArr; - private CfgEdgeImpl[] edgeArr; - - public CfgEnv(ControlFlowGraph cfg) { - this.cfg = cfg; - int blockCount = cfg.getBasicBlocks().size(); - CfgNodeImpl[] nodes = new CfgNodeImpl[blockCount]; - Map block2nodeMap = new HashMap<>(); - Map> inputMap = new HashMap<>(); - ArrayList allEdges = new ArrayList<>(); - List blocks = cfg.getBasicBlocks(); - //create nodes - for(int idx=0 ; idx < blockCount ; idx++) { - BasicBlock b = blocks.get(idx); - - String description = "Name: " + b.getName() + "\n"; - description += "BCI: [" + b.getFromBci() + "," + b.getToBci() + "]\n"; - if (b.getLoopDepth() > 0) { - description += "Loop " + b.getLoopIndex() + " Depth " + b.getLoopDepth() + "\n"; - } - description += "Predecessors: " + getBlockList(b.getPredecessors()) + "\n"; - description += "Successors: " + getBlockList(b.getSuccessors()) + "\n"; - description += "XHandlers: " + getBlockList(b.getXhandlers()); - if (b.getDominator() != null) { - description += "\nDominator: " + b.getDominator().getName(); - } - nodes[idx] = new CfgNodeImpl(b, idx, description); - block2nodeMap.put(b, nodes[idx]); - } - - - //create edges - Set cache = new HashSet<>();//avoids identical edges with same source and same target - for(int i = 0 ; i < blockCount ; i++) { - BasicBlock b = blocks.get(i); - List outputEdges = new ArrayList<>(); - - Set successors = new HashSet<>(); - successors.addAll(b.getSuccessors()); - successors.addAll(b.getXhandlers()); - for(BasicBlock sb : successors) { - CfgNodeImpl succNode = block2nodeMap.get(sb); - CfgEdgeImpl edge = new CfgEdgeImpl(nodes[i], succNode); - if(cache.contains(edge.toString())) - continue; - cache.add(edge.toString()); - //check for symtric edges - if(sb.getXhandlers().contains(b) || sb.getSuccessors().contains(b)) - edge.setSymmetric(true); - outputEdges.add(edge); - } - allEdges.addAll(outputEdges); - nodes[i].setOutputEdges(outputEdges.toArray(new CfgEdgeImpl[outputEdges.size()])); - } - - for(CfgEdgeImpl e: allEdges) { - //CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode(); - CfgNodeImpl tar = (CfgNodeImpl) e.getTargetNode(); - Set set = inputMap.get(tar); - if( set == null) { - set = new HashSet<>(); - set.add(e); - inputMap.put(tar, set); - } - set.add(e); - } - for(CfgNodeImpl n : nodes){ - Set inputEdges = inputMap.get(n); - if(inputEdges == null) continue; - n.setInputEdges(inputEdges.toArray(new CfgEdgeImpl[inputEdges.size()])); - } - CfgEdgeImpl[] edges = allEdges.toArray(new CfgEdgeImpl[allEdges.size()]); - this.edgeArr=edges; - this.nodeArr=nodes; - CfgNodeImpl rootNode = nodeArr[0]; - setNodeLevels(rootNode); - indexLoops(rootNode); - - } - - - private String getBlockList(List blocks) { - if (blocks.size() == 0) { - return "None"; - } - StringBuilder sb = new StringBuilder(); - String prefix = ""; - for (BasicBlock b : blocks) { - sb.append(prefix).append(b.getName()); - prefix = ", "; - } - return sb.toString(); - } - - - public CfgNode[] getNodes(){ - return this.nodeArr; - } - - public CfgEdge[] getEdges(){ - return this.edgeArr; - } - - public Map getLoopMap() { - return loopMap; - } - - public void setLoopMap(Map loopMap) { - this.loopMap = loopMap; - } - - private void indexLoops(CfgNodeImpl rootNode){ - LoopEnv env = new LoopEnv(Arrays.asList(nodeArr)); - loopDetection(env, rootNode); - calcLoopDepth(env); - - int loopIndex=1; - - for(LoopInfo info : env.loopMap.values()) { - info.setLoopIndex(loopIndex++); - info.setLoopDepth(info.getHeader().getLoopDepth()); - for(CfgNode n : info.getMembers()){ - if(n.getLoopDepth()>info.getLoopDepth()) continue; - CfgNodeImpl ni = (CfgNodeImpl) n; - ni.setLoopDepth(info.getLoopDepth()); - ni.setLoopIndex(info.getLoopIndex()); - } - } - - for(LoopInfo info : env.loopMap.values()) { - HashSet members = new HashSet<>(info.getMembers()); - members.remove(info.getHeader());//remove own header - for(CfgNode n: members){ - if(n.isLoopHeader()) { - LoopInfo memberInfo = env.loopMap.get(n); - if (info.getLoopDepth() == memberInfo.getLoopDepth()-1) - memberInfo.setParent(info); - } - } - } - this.loopMap = env.loopMap; - } - - - private class LoopEnv { - Set allNodes; - Set activeNodes; - Set visitedNodes; - Map loopMap; - private int loopIndex=0; - - public LoopEnv(Collection nodes){ - allNodes = new HashSet<>(nodes); - activeNodes = new HashSet<>(2 * allNodes.size()); - visitedNodes = new HashSet<>(2 * allNodes.size()); - loopMap = new HashMap<>(); - } - - public int getLoopIndex(){ - return ++loopIndex; - } - } - - - private void loopDetection(LoopEnv env, CfgNodeImpl root) { - for (CfgNodeImpl n : env.allNodes) { - n.setLoopHeader(false); - for (CfgEdge e : n.getInputEdges()) { - CfgEdgeImpl ei = (CfgEdgeImpl) e; - ei.setBackEdge(false); - } - } - visit(env, root, null); - } - - - - private void visit(LoopEnv env, CfgNodeImpl n, CfgEdgeImpl e) { - if (env.activeNodes.contains(n)) { - // This node is b loop header! - n.setLoopHeader(true); - e.setBackEdge(true); - } else if (!env.visitedNodes.contains(n)) { - env.visitedNodes.add(n); - env.activeNodes.add(n); - - for (CfgEdge edge : n.getOutputEdges()) { - if(!edge.getTargetNode().isOSR()) { - CfgEdgeImpl ei = (CfgEdgeImpl) edge; - CfgNodeImpl ni = (CfgNodeImpl) edge.getTargetNode(); - visit(env, ni, ei); - } - } - env.activeNodes.remove(n); - } - } - - - - private void calcLoopDepth(LoopEnv env) { - for (CfgNodeImpl n : env.allNodes) { - env.visitedNodes.clear(); - - if (n.isLoopHeader()) { - LoopInfo loop = new LoopInfo(); - loop.setHeader(n); - n.setLoopIndex(env.getLoopIndex()); - HashSet members = new HashSet<>(); - loop.setMembers(members); - members.add(n); - env.loopMap.put(loop.getHeader(), loop); - int loopDepth = n.getLoopDepth() + 1; - loop.setLoopDepth(loopDepth); - n.setLoopDepth(loopDepth); - for (CfgEdge e : n.getInputEdges()) { - if (e.isBackEdge() && !e.getSourceNode().isOSR()) { - CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode(); - backwardIteration(env, n, src, loop); - loop.getBackEdges().add(e); - } - } - } - } - } - - - private void backwardIteration(LoopEnv env, CfgNodeImpl endNode, CfgNodeImpl n, LoopInfo loop) { - if (endNode != n && !env.visitedNodes.contains(n)) { - env.visitedNodes.add(n); - - for (CfgEdge e : n.getInputEdges()) { - if (!e.getSourceNode().isOSR()) { - CfgNodeImpl src = (CfgNodeImpl) e.getSourceNode(); - backwardIteration(env, endNode, src, loop); - } - } - loop.getMembers().add(n); - n.setLoopDepth(n.getLoopDepth() + 1); - } - } - - private void setNodeLevels(CfgNode rootNode){ - Set cache = new HashSet<>(); - Queue queue = new LinkedList<>(); - queue.add(rootNode); - cache.add(rootNode); - int level=0; - int[] nodeCount = new int[2]; - nodeCount[0]=1; - while(!queue.isEmpty()){ - CfgNodeImpl curNode = (CfgNodeImpl) queue.poll(); - curNode.setLevel(level); - nodeCount[0]--; - for(CfgEdge outEdge : curNode.getOutputEdges()) { - CfgNode succNode = outEdge.getTargetNode(); - if(cache.contains(succNode)) continue; - cache.add(succNode); - queue.add(succNode); - nodeCount[1]++; - } - if(nodeCount[0]==0){ - nodeCount[0]=nodeCount[1]; - nodeCount[1]=0; - level++; - } - } - } - - public ControlFlowGraph getCfg() { - return cfg; - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgNode.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgNode.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -package at.ssw.visualizer.cfg.model; - -import at.ssw.visualizer.model.cfg.BasicBlock; - - -public interface CfgNode { - //testers - public boolean isOSR(); - public boolean isRoot(); - public boolean isLoopHeader(); - public boolean isLoopMember(); - - //getters - public int getLevel(); - public int getLoopDepth(); - public int getLoopIndex(); - public int getNodeIndex(); - public CfgEdge[] getInputEdges(); - public CfgEdge[] getOutputEdges(); - public BasicBlock getBasicBlock(); - public String getDescription(); - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgNodeImpl.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/CfgNodeImpl.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -package at.ssw.visualizer.cfg.model; - -import at.ssw.visualizer.model.cfg.BasicBlock; -import java.awt.Color; - - - -public class CfgNodeImpl implements CfgNode { - private int nodeIndex; - private BasicBlock basicBlock; - private int level; - private int loopDepth=0; - private int loopIndex=0; - private boolean osr=false; - private CfgNodeImpl dominator=null; - private CfgEdgeImpl[] inputEdges = new CfgEdgeImpl[0]; - private CfgEdgeImpl[] outputEdges = new CfgEdgeImpl[0]; - private String description; - private Color customColor=null; - private boolean loopHeader; - - public CfgNodeImpl(BasicBlock bb, int nodeIndex, String description) { - this.basicBlock = bb; - this.nodeIndex = nodeIndex; - this.description = description; - - if (bb.getPredecessors().size() == 1) { - BasicBlock pred = bb.getPredecessors().get(0); - boolean isStd = pred.getPredecessors().size() == 0; - if (isStd) { - for (String s : bb.getFlags()) { - if (s.equals("osr")) { - osr = true; - break; - } - } - } - } - } - - public int getNodeIndex() { - return nodeIndex; - } - - - public void setDominator(CfgNodeImpl dominator) { - this.dominator = dominator; - } - - public void setLevel(int level) { - this.level = level; - } - - public void setLoopDepth(int loopDepth) { - this.loopDepth = loopDepth; - } - - public void setLoopHeader(boolean loopHeader) { - this.loopHeader = loopHeader; - } - - public void setLoopIndex(int loopIndex) { - this.loopIndex = loopIndex; - } - - public void setNodeIndex(int nodeIndex) { - this.nodeIndex = nodeIndex; - } - - public boolean isRoot() { - return nodeIndex==0; - } - - public boolean isLoopHeader() { - return loopHeader; - } - - public boolean isLoopMember() { - return loopIndex > 0; - } - - public int getLevel() { - return level; - } - - public BasicBlock getBasicBlock() { - return basicBlock; - } - - public int getLoopDepth() { - return loopDepth; - } - - public int getLoopIndex() { - return loopIndex; - } - - public boolean isOSR() { - return osr; - } - - @Override - public String toString(){ - return basicBlock.getName(); - } - - public void setInputEdges(CfgEdgeImpl[] inputEdges){ - this.inputEdges = inputEdges; - } - - - public void setOutputEdges(CfgEdgeImpl[] outputEdges){ - this.outputEdges = outputEdges; - } - - public CfgEdge[] getInputEdges() { - return this.inputEdges; - } - - public CfgEdge[] getOutputEdges() { - return outputEdges; - } - - public String getDescription() { - return description; - } - - public void setColor(Color color) { - this.customColor=color; - } - - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/LoopInfo.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/model/LoopInfo.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -package at.ssw.visualizer.cfg.model; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - - -public class LoopInfo { - private CfgNode header;//the target node of the backedge - private int loopIndex; //index of the min cycleSet - private int loopDepth; //nested depth >=1 - private LoopInfo parent=null; - private Set members; - private List backEdges = new ArrayList<>();//dfs backEdge - - protected void setLoopDepth(int depth) { - this.loopDepth=depth; - } - - protected void setLoopIndex(int loopIndex) { - this.loopIndex = loopIndex; - } - - public int getLoopDepth() { - return loopDepth; - } - - public Set getMembers() { - return members; - } - - protected void setMembers(Set members) { - this.members = members; - } - - public int getLoopIndex() { - return loopIndex; - } - - protected void setParent(LoopInfo parent) { - this.parent = parent; - } - - public LoopInfo getParent(){ - return parent; - } - - public List getBackEdges() { - return backEdges; - } - - public CfgNode getHeader() { - return header; - } - - protected void setHeader(CfgNode header) { - this.header = header; - } - - @Override - public String toString(){ - return "Loop(" + header.toString()+ ")-->" + members.toString(); - } - - - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsCategory.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsCategory.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -package at.ssw.visualizer.cfg.preferences; - -import javax.swing.Icon; -import javax.swing.ImageIcon; -import org.netbeans.spi.options.OptionsCategory; -import org.netbeans.spi.options.OptionsPanelController; -import org.openide.util.ImageUtilities; - -/** - * Descriptor for the settings page displayed in the options dialog. - * - * @author Bernhard Stiftner - */ -public class CFGOptionsCategory extends OptionsCategory { - - public OptionsPanelController create() { - return new CFGOptionsPanelController(); - } - - public String getCategoryName() { - return "Control Flow Graph"; - } - - @Override - public Icon getIcon() { - return new ImageIcon(ImageUtilities.loadImage("at/ssw/visualizer/cfg/icons/cfg32.gif")); - } - - public String getTitle() { - return "CFG Visualizer"; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsPanel.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsPanel.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,482 +0,0 @@ -package at.ssw.visualizer.cfg.preferences; - -import java.awt.Color; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.List; -import javax.swing.AbstractAction; -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.JButton; -import javax.swing.JComponent; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.SwingConstants; - -/** - * The actual component for changing the CFG visualizer settings. - * - * @author Bernhard Stiftner - * @author Rumpfhuber Stefan - */ -public class CFGOptionsPanel extends JPanel { - - List elements = new ArrayList<>(); - - /** Creates a new instance of CFGOptionsPanel */ - public CFGOptionsPanel() { - setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); - JPanel cfgPanel = new JPanel(new GridBagLayout()); - - // color/font settings - addColorChooser(cfgPanel, "Background color: ", new ColorChooser(CfgPreferences.PROP_BACKGROUND_COLOR){ - @Override - public void apply() { - CfgPreferences.getInstance().setBackgroundColor(getColor()); - } - - @Override - public void update() { - this.originalColor = CfgPreferences.getInstance().getBackgroundColor(); - setColor(this.originalColor); - } - - public void reset() { - this.setColor(CfgPreferencesDefaults.DEFAULT_BACKGROUND_COLOR); - } - - - - }); - addColorChooser(cfgPanel, "Back edge color: ", new ColorChooser(CfgPreferences.PROP_BACK_EDGE_COLOR){ - - @Override - public void apply() { - CfgPreferences.getInstance().setBackedgeColor(getColor()); - } - - @Override - public void update() { - this.originalColor = CfgPreferences.getInstance().getBackedgeColor(); - this.setColor(this.originalColor); - - } - - public void reset() { - this.setColor(CfgPreferencesDefaults.DEFAULT_BACKEDGE_COLOR); - } - }); - addColorChooser(cfgPanel, "Edge color: ", new ColorChooser(CfgPreferences.PROP_EDGE_COLOR){ - - @Override - public void apply() { - CfgPreferences.getInstance().setEdgeColor(getColor()); - } - - @Override - public void update() { - this.originalColor = CfgPreferences.getInstance().getEdgeColor(); - setColor(this.originalColor); - } - - public void reset() { - this.setColor(CfgPreferencesDefaults.DEFAULT_EDGE_COLOR); - } - - }); - addColorChooser(cfgPanel, "Exception edge color: ", new ColorChooser(CfgPreferences.PROP_EXCEPTION_EDGE_COLOR){ - - @Override - public void apply() { - CfgPreferences.getInstance().setExceptionEdgeColor(getColor()); - } - - @Override - public void update() { - this.originalColor = CfgPreferences.getInstance().getExceptionEdgeColor(); - setColor(this.originalColor); - - } - - public void reset() { - this.setColor(CfgPreferencesDefaults.DEFAULT_EXCEPTIONEDGE_COLOR); - } - }); - addColorChooser(cfgPanel, "Node color: ", new ColorChooser(CfgPreferences.PROP_NODE_COLOR){ - - @Override - public void apply() { - CfgPreferences.getInstance().setNodeColor(getColor()); - } - - @Override - public void update() { - this.originalColor = CfgPreferences.getInstance().getNodeColor(); - setColor(this.originalColor); - - } - - public void reset() { - this.setColor(CfgPreferencesDefaults.DEFAUT_NODE_COLOR); - } - }); - addColorChooser(cfgPanel, "Text color: ", new ColorChooser(CfgPreferences.PROP_TEXT_COLOR){ - - @Override - public void apply() { - CfgPreferences.getInstance().setTextColor(getColor()); - } - - @Override - public void update() { - this.originalColor = CfgPreferences.getInstance().getTextColor(); - - } - - public void reset() { - this.setColor(CfgPreferencesDefaults.DEFAULT_TEXT_COLOR); - } - }); - addColorChooser(cfgPanel, "Border color: ", new ColorChooser(CfgPreferences.PROP_BORDER_COLOR){ - - @Override - public void apply() { - CfgPreferences.getInstance().setBorderColor(getColor()); - } - - @Override - public void update() { - this.originalColor = CfgPreferences.getInstance().getBorderColor(); - setColor(this.originalColor); - - } - public void reset() { - this.setColor(CfgPreferencesDefaults.DEFAULT_BORDER_COLOR); - } - }); - addColorChooser(cfgPanel, "Selected Nodes color: ", new ColorChooser(CfgPreferences.PROP_SELECTION_COLOR_FG){ - - @Override - public void apply() { - CfgPreferences.getInstance().setSelectionColorForeground(getColor()); - } - - @Override - public void update() { - this.originalColor = CfgPreferences.getInstance().getSelectionColorForeground(); - setColor(this.originalColor); - } - - public void reset() { - this.setColor(CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_FOREGROUND); - } - }); - addColorChooser(cfgPanel, "Selection Rect color: ", new ColorChooser(CfgPreferences.PROP_SELECTION_COLOR_BG){ - - @Override - public void apply() { - CfgPreferences.getInstance().setSelectionColorBackground(getColor()); - } - - @Override - public void update() { - this.originalColor = CfgPreferences.getInstance().getSelectionColorBackground(); - setColor(this.originalColor); - } - - public void reset() { - this.setColor(CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_BACKGROUND); - } - }); - addFontChooser(cfgPanel, "Text font: ", new FontChooser(CfgPreferences.PROP_TEXT_FONT){ - - @Override - public void apply() { - CfgPreferences.getInstance().setTextFont(getSelectedFont()); - } - - @Override - public void update() { - this.originalFont = CfgPreferences.getInstance().getTextFont(); - this.setSelectedFont(originalFont); - - } - - public void reset() { - this.setSelectedFont(CfgPreferencesDefaults.DEFAULT_TEXT_FONT); - } - }); - - // flags editor - addFlagsEditor(cfgPanel, "Flags: "); - add(cfgPanel); - - // add update button - Box hBox = new Box(BoxLayout.X_AXIS); - hBox.add(new JButton(new ResetAction())); - hBox.add(Box.createHorizontalGlue()); - add(hBox); - - add(Box.createVerticalGlue()); - } - - public void update() { - for (ConfigurationElement e : elements) { - e.update(); - } - } - - public void cancel() { - for (ConfigurationElement e : elements) { - e.update(); - } - } - - public void applyChanges() { - for (ConfigurationElement e : elements) { - if(e.isChanged()) - e.apply(); - } - } - - public boolean isDataValid() { - return true; - } - - public boolean isChanged() { - for (ConfigurationElement e : elements) { - if (e.isChanged()) { - return true; - } - } - return false; - } - - public void loadDefault() { - for (ConfigurationElement e : elements) { - e.reset(); - } - } - - private void addColorChooser(JComponent c, String displayName, ColorChooser chooser) { - GridBagLayout layout = (GridBagLayout)c.getLayout(); - GridBagConstraints constraints = new GridBagConstraints(); - constraints.insets = new Insets(3, 3, 3, 3); - constraints.weightx = 0.0; - constraints.fill = GridBagConstraints.NONE; - constraints.anchor = GridBagConstraints.EAST; - JLabel label = new JLabel(displayName, JLabel.TRAILING); - layout.setConstraints(label, constraints); - c.add(label); - constraints.anchor = GridBagConstraints.WEST; - constraints.gridwidth = GridBagConstraints.REMAINDER; - layout.setConstraints(chooser, constraints); - c.add(chooser); - elements.add(chooser); - label.setLabelFor(chooser); - } - - - - private void addFontChooser(JComponent c, String displayName, FontChooser chooser) { - GridBagLayout layout = (GridBagLayout)c.getLayout(); - GridBagConstraints constraints = new GridBagConstraints(); - constraints.insets = new Insets(3, 3, 3, 3); - constraints.weightx = 0.0; - constraints.fill = GridBagConstraints.NONE; - constraints.anchor = GridBagConstraints.EAST; - JLabel label = new JLabel(displayName, JLabel.TRAILING); - layout.setConstraints(label, constraints); - c.add(label); - constraints.insets = new Insets(3, 3, 3, 1); - constraints.weightx = 1.0; - constraints.fill = GridBagConstraints.HORIZONTAL; - constraints.anchor = GridBagConstraints.CENTER; - layout.setConstraints(chooser.getPreview(), constraints); - c.add(chooser.getPreview()); - constraints.insets = new Insets(3, 1, 3, 3); - constraints.weightx = 0.0; - constraints.fill = GridBagConstraints.NONE; - constraints.anchor = GridBagConstraints.EAST; - constraints.gridwidth = GridBagConstraints.REMAINDER; - layout.setConstraints(chooser.getButton(), constraints); - c.add(chooser.getButton()); - elements.add(chooser); - label.setLabelFor(chooser.getButton()); - } - - private void addFlagsEditor(JComponent c, String displayName) { - GridBagLayout layout = (GridBagLayout)c.getLayout(); - GridBagConstraints constraints = new GridBagConstraints(); - constraints.insets = new Insets(3, 3, 3, 3); - constraints.weightx = 0.0; - constraints.fill = GridBagConstraints.NONE; - constraints.anchor = GridBagConstraints.NORTHEAST; - FlagsEditor flagsEditor = new FlagsEditor(); - JLabel flagsLabel = new JLabel(displayName, JLabel.TRAILING); - flagsLabel.setVerticalAlignment(SwingConstants.TOP); - layout.setConstraints(flagsLabel, constraints); - c.add(flagsLabel); - constraints.weightx = 1.0; - constraints.weighty = 1.0; - constraints.fill = GridBagConstraints.BOTH; - constraints.anchor = GridBagConstraints.CENTER; - constraints.gridwidth = GridBagConstraints.REMAINDER; - layout.setConstraints(flagsEditor, constraints); - c.add(flagsEditor); - elements.add(flagsEditor); - flagsLabel.setLabelFor(flagsEditor); - } - - - - - interface ConfigurationElement { - - public boolean isChanged(); - - //apply changes to preferences - public void apply(); - - //optain current value from preferences - public void update(); - - //reset to default value - public void reset(); - - } - - abstract class ColorChooser extends ColorChooserButton implements ConfigurationElement { - - Color originalColor;//the color before any change - String propertyName; - - public ColorChooser(String propertyName) { - this.propertyName = propertyName; - } - - public boolean isChanged() { - return !originalColor.equals(getColor()); - } - - - public abstract void apply(); - public abstract void update(); - - } - - - abstract class FontChooser implements ConfigurationElement, ActionListener { - - Font originalFont; - Font selectedFont; - String propertyName; - JTextField preview; - JButton button; - - public FontChooser(String propertyName) { - this.propertyName = propertyName; - preview = new JTextField(""); - preview.setEditable(false); - button = new JButton("..."); - button.setMargin(new Insets(0, 0, 0, 0)); - button.addActionListener(this); - } - - public boolean isChanged() { - return !originalFont.equals(selectedFont); - } - - public abstract void apply(); - - public abstract void update(); - - public abstract void reset(); - - public JTextField getPreview() { - return preview; - } - - public JButton getButton() { - return button; - }; - - public Font getSelectedFont() { - return selectedFont; - } - - public void setSelectedFont(Font f) { - selectedFont = f; - preview.setText(fontToString(f)); - preview.revalidate(); - } - - public void actionPerformed(ActionEvent e) { - setSelectedFont(FontChooserDialog.show(selectedFont)); - } - - public String fontToString(Font font) { - StringBuffer sb = new StringBuffer(); - sb.append(font.getName()); - sb.append(" "); - sb.append(font.getSize()); - if (font.isBold()) { - sb.append(" bold"); - } - if (font.isItalic()) { - sb.append(" italic"); - } - return sb.toString(); - } - - } - - class FlagsEditor extends FlagsEditorPanel implements ConfigurationElement { - - FlagsSetting originalFlags; - - public FlagsEditor() { - super(null); - } - - public boolean isChanged() { - return !originalFlags.getFlagString().equals(getFlagString()); - } - - public void apply() { - CfgPreferences.getInstance().setFlagsSetting(new FlagsSetting(getFlagString())); - update(); - } - - public void update() { - originalFlags = CfgPreferences.getInstance().getFlagsSetting(); - setFlagString(originalFlags.getFlagString()); - } - - public void reset() { - FlagsSetting defaultFlags = new FlagsSetting(CfgPreferencesDefaults.DEFAULT_FLAGSTRING); - setFlagString(defaultFlags.getFlagString()); - colorButton.setColor(getParent().getBackground()); - } - - } - - class ResetAction extends AbstractAction { - - public ResetAction() { - super("Reset"); - } - - public void actionPerformed(ActionEvent e) { - CFGOptionsPanel.this.loadDefault(); - } - - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsPanelController.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CFGOptionsPanelController.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -package at.ssw.visualizer.cfg.preferences; - -import java.beans.PropertyChangeListener; -import javax.swing.JComponent; -import org.netbeans.spi.options.OptionsPanelController; -import org.openide.util.HelpCtx; -import org.openide.util.Lookup; - -/** - * Controller for the settings page displayed in the options dialog. - * - * @author Bernhard Stiftner - */ -public class CFGOptionsPanelController extends OptionsPanelController { - - CFGOptionsPanel optionsPanel; - - - public void update() { - getOptionsPanel().update(); - } - - public void applyChanges() { - getOptionsPanel().applyChanges(); - } - - public void cancel() { - getOptionsPanel().cancel(); - } - - public boolean isValid() { - return getOptionsPanel().isDataValid(); - } - - public boolean isChanged() { - return getOptionsPanel().isChanged(); - } - - public JComponent getComponent(Lookup masterLookup) { - return getOptionsPanel(); - } - - public HelpCtx getHelpCtx() { - return HelpCtx.DEFAULT_HELP; - } - - public void addPropertyChangeListener(PropertyChangeListener l) { - getOptionsPanel().addPropertyChangeListener(l); - } - - //todo: investigate - who removes the changelistener ? - public void removePropertyChangeListener(PropertyChangeListener l) { - getOptionsPanel().removePropertyChangeListener(l); - } - - private CFGOptionsPanel getOptionsPanel() { - if (optionsPanel == null) { - optionsPanel = new CFGOptionsPanel(); - } - return optionsPanel; - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CfgPreferences.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CfgPreferences.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,239 +0,0 @@ -package at.ssw.visualizer.cfg.preferences; - -import java.awt.Color; -import java.awt.Font; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.prefs.Preferences; -import javax.swing.event.EventListenerList; -import org.openide.util.NbPreferences; - -/** - * Replacement for old CFGSettings to remove dependency on deprecated SystemOption package - * - * @author Rumpfhuber Stefan - */ -public class CfgPreferences { - public static final String PROP_FLAGS = "flagsPreference"; - public static final String PROP_TEXT_FONT = "textFontPreference"; - public static final String PROP_TEXT_COLOR = "textColorPreference"; - public static final String PROP_NODE_COLOR = "nodeColorPreference"; - public static final String PROP_EDGE_COLOR = "edgeColorPreference"; - public static final String PROP_BORDER_COLOR = "borderColorPreference"; - public static final String PROP_BACK_EDGE_COLOR = "backEdgeColorPreference"; - public static final String PROP_BACKGROUND_COLOR = "backgroundColorPreference"; - public static final String PROP_SELECTION_COLOR_FG = "selectionColorFgPreference"; - public static final String PROP_SELECTION_COLOR_BG = "selectionColorBgPreference"; - public static final String PROP_EXCEPTION_EDGE_COLOR = "exceptionEdgeColorPreference"; - - private static final String PROP_FONTNAME = "_FontFamily"; - private static final String PROP_FONTSIZE = "_FontSize"; - private static final String PROP_FONTSTYLE = "_FontStyle"; - - protected static final String nodeName = "CfgPreferences"; - - private static CfgPreferences instance = new CfgPreferences(); - private EventListenerList listenerList; - - private FlagsSetting flagsSetting; - private Color node_color; - private Color background_color; - private Color backedge_color; - private Color edge_color; - private Color border_color; - private Color exceptionEdgeColor; - private Color text_color; - private Font text_font; - private Color selection_color_fg; - private Color selection_color_bg; - - - private CfgPreferences(){ - listenerList = new EventListenerList(); - init(); - } - - public static CfgPreferences getInstance(){ - return instance; - } - - protected final Preferences getPreferences() { - return NbPreferences.forModule(this.getClass()).node("options").node(nodeName); - } - - - protected void init(){ - Preferences prefs = this.getPreferences(); - String flagString = prefs.get(PROP_FLAGS, CfgPreferencesDefaults.DEFAULT_FLAGSTRING); - flagsSetting = new FlagsSetting(flagString); - node_color = this.getColorProperty(PROP_NODE_COLOR, CfgPreferencesDefaults.DEFAUT_NODE_COLOR); - background_color = this.getColorProperty(PROP_BACKGROUND_COLOR, CfgPreferencesDefaults.DEFAULT_BACKGROUND_COLOR); - backedge_color = this.getColorProperty(PROP_BACK_EDGE_COLOR, CfgPreferencesDefaults.DEFAULT_BACKEDGE_COLOR); - edge_color = this.getColorProperty(PROP_EDGE_COLOR, CfgPreferencesDefaults.DEFAULT_EDGE_COLOR); - selection_color_fg= this.getColorProperty(PROP_SELECTION_COLOR_FG, CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_FOREGROUND); - border_color = this.getColorProperty(PROP_BORDER_COLOR, CfgPreferencesDefaults.DEFAULT_BORDER_COLOR); - exceptionEdgeColor = this.getColorProperty(PROP_EXCEPTION_EDGE_COLOR, CfgPreferencesDefaults.DEFAULT_EXCEPTIONEDGE_COLOR); - text_color= this.getColorProperty(PROP_TEXT_COLOR, CfgPreferencesDefaults.DEFAULT_TEXT_COLOR); - selection_color_bg = this.getColorProperty(PROP_SELECTION_COLOR_BG, CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_BACKGROUND); - selection_color_fg = this.getColorProperty(PROP_SELECTION_COLOR_FG, CfgPreferencesDefaults.DEFAULT_SELECTION_COLOR_FOREGROUND); - text_font = this.getFontProperty(PROP_TEXT_FONT, CfgPreferencesDefaults.DEFAULT_TEXT_FONT); - } - - private void firePropertyChange(String propertyName, Object oldValue, Object newValue) { - Object[] listeners = listenerList.getListenerList(); - - PropertyChangeEvent event = new PropertyChangeEvent(this, propertyName, oldValue, newValue); - for (int i = listeners.length - 2; i >= 0; i -= 2) { - if (listeners[i] == PropertyChangeListener.class) { - ((PropertyChangeListener) listeners[i+1]).propertyChange(event); - } - } - } - - private Font getFontProperty(String propName, Font defaultFont){ - Preferences prefs = this.getPreferences(); - String fontName = prefs.get(propName+PROP_FONTNAME, defaultFont.getFamily()); - int fontSize = prefs.getInt(propName+PROP_FONTSIZE, defaultFont.getSize()); - int fontStyle = prefs.getInt(propName+PROP_FONTSTYLE, defaultFont.getStyle()); - return new Font(fontName, fontStyle, fontSize); - } - - private Color getColorProperty(String propName, Color defaultColor){ - Preferences prefs = this.getPreferences(); - int srgb = prefs.getInt(propName, defaultColor.getRGB()); - if(srgb == defaultColor.getRGB()) - return defaultColor; - return new Color(srgb); - } - - public Color getBackedgeColor() { - return backedge_color; - } - - public Color getBackgroundColor() { - return background_color; - } - - public Color getBorderColor() { - return border_color; - } - - public Color getEdgeColor() { - return edge_color; - } - - public Color getExceptionEdgeColor() { - return exceptionEdgeColor; - } - - public Color getNodeColor() { - return node_color; - } - - public Color getSelectionColorForeground() { - return selection_color_fg; - } - - public Color getSelectionColorBackground() { - return selection_color_bg; - } - - public Color getTextColor() { - return text_color; - } - - public Font getTextFont() { - return text_font; - } - - public FlagsSetting getFlagsSetting() { - return flagsSetting; - } - - - public void setFlagsSetting(FlagsSetting flagsSetting) { - FlagsSetting old = this.getFlagsSetting(); - this.flagsSetting = flagsSetting; - Preferences prefs = getPreferences(); - firePropertyChange(PROP_FLAGS, old, flagsSetting); - prefs.put(PROP_FLAGS, flagsSetting.getFlagString()); - } - - - public void setTextFont(Font text_font) { - Font old = this.getTextFont(); - Preferences prefs = getPreferences(); - this.text_font = text_font; - firePropertyChange(PROP_TEXT_FONT, old, text_font); - prefs.put(PROP_TEXT_FONT + PROP_FONTNAME , text_font.getFamily()); - prefs.putInt(PROP_TEXT_FONT + PROP_FONTSIZE, text_font.getSize()); - prefs.putInt(PROP_TEXT_FONT + PROP_FONTSTYLE, text_font.getStyle()); - } - - public void setBackedgeColor(Color backedge_color) { - Color old = this.getBackedgeColor(); - this.backedge_color = backedge_color; - firePropertyChange(PROP_BACK_EDGE_COLOR, old, backedge_color); - getPreferences().putInt(PROP_BACK_EDGE_COLOR, backedge_color.getRGB()); - } - - public void setBackgroundColor(Color bg_color) { - Color old = this.getBackgroundColor(); - background_color = bg_color; - firePropertyChange(PROP_BACKGROUND_COLOR, old, bg_color ); - getPreferences().putInt(PROP_BACKGROUND_COLOR, bg_color.getRGB()); - } - - public void setBorderColor(Color border_color) { - Color old = getBorderColor(); - this.border_color = border_color; - firePropertyChange(PROP_BORDER_COLOR, old, border_color ); - getPreferences().putInt(PROP_BORDER_COLOR, border_color.getRGB()); - } - - public void setEdgeColor(Color edge_color) { - Color old = getEdgeColor(); - this.edge_color = edge_color; - firePropertyChange(PROP_EDGE_COLOR, old, edge_color); - getPreferences().putInt(PROP_EDGE_COLOR, edge_color.getRGB()); - } - - public void setNodeColor(Color node_color) { - Color old = getNodeColor(); - this.node_color = node_color; - firePropertyChange(PROP_NODE_COLOR, old, node_color); - getPreferences().putInt(PROP_NODE_COLOR, node_color.getRGB()); - - } - - public void setSelectionColorForeground(Color selection_color) { - Color old = this.getSelectionColorForeground(); - this.selection_color_fg = selection_color; - firePropertyChange(PROP_SELECTION_COLOR_FG, old, selection_color); - getPreferences().putInt(PROP_SELECTION_COLOR_FG, selection_color.getRGB()); - } - - public void setSelectionColorBackground(Color selection_color) { - Color old = this.getSelectionColorBackground(); - this.selection_color_bg = selection_color; - firePropertyChange(PROP_SELECTION_COLOR_BG, old, selection_color); - getPreferences().putInt(PROP_SELECTION_COLOR_BG, selection_color.getRGB()); - } - - public void setTextColor(Color text_color) { - Color old = this.getTextColor(); - this.text_color = text_color; - firePropertyChange(PROP_TEXT_COLOR, old, text_color); - getPreferences().putInt(PROP_TEXT_COLOR, text_color.getRGB()); - } - - public void setExceptionEdgeColor(Color exceptionEdgeColor) { - Color old = this.getExceptionEdgeColor(); - this.exceptionEdgeColor = exceptionEdgeColor; - firePropertyChange(PROP_EXCEPTION_EDGE_COLOR, old, exceptionEdgeColor); - getPreferences().putInt(PROP_EXCEPTION_EDGE_COLOR, exceptionEdgeColor.getRGB()); - } - - - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CfgPreferencesDefaults.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/CfgPreferencesDefaults.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -package at.ssw.visualizer.cfg.preferences; - -import java.awt.Color; -import java.awt.Font; - -/** - * Default Configuration for options panel - * - * @author Rumpfhuber Stefan - */ -public final class CfgPreferencesDefaults { - public static final String DEFAULT_FLAGSTRING = "std(224,224,128);osr(224,224,0);ex(128,128,224);sr(128,224,128);llh(224,128,128);lle(224,192,192);plh(128,224,128);bb(160,0,0);ces(192,192,192)"; - public static final Color DEFAUT_NODE_COLOR = new Color(208, 208, 208); - public static final Color DEFAULT_BACKGROUND_COLOR = new Color(255, 255, 255); - public static final Color DEFAULT_BACKEDGE_COLOR = new Color(160, 0, 0); - public static final Color DEFAULT_EDGE_COLOR = new Color(0, 0, 0); - public static final Color DEFAULT_SELECTION_COLOR_FOREGROUND = Color.BLUE; - public static final Color DEFAULT_SELECTION_COLOR_BACKGROUND = Color.BLUE; - public static final Color DEFAULT_BORDER_COLOR = new Color(0, 0, 0); - public static final Color DEFAULT_EXCEPTIONEDGE_COLOR = new Color(0, 0, 160); - public static final Color DEFAULT_TEXT_COLOR = new Color(0, 0, 0); - public static final Font DEFAULT_TEXT_FONT = new Font("Dialog", Font.PLAIN, 18); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/ColorChooserButton.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/ColorChooserButton.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -package at.ssw.visualizer.cfg.preferences; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import javax.swing.Icon; -import javax.swing.JButton; -import javax.swing.JColorChooser; - -/** - * A color selection button. It will preview the currently selected color as - * an icon. Clicking the button will bring up the JColorChooser dialog. - * - * @author Bernhard Stiftner - */ -public class ColorChooserButton extends JButton implements ActionListener { - - public static final Dimension ICON_SIZE = new Dimension(24, 8); - - Color color; - boolean colorChooserEnabled = true; // bring up dialog when clicked? - - - public ColorChooserButton() { - this(Color.black); - } - - public ColorChooserButton(Color defaultColor) { - setIcon(new ColorBoxIcon()); - addActionListener(this); - color = defaultColor; - Dimension size = new Dimension(ICON_SIZE); - size.width += getInsets().left + getInsets().right; - size.height += getInsets().top + getInsets().bottom; - setPreferredSize(size); - } - - public void setColor(Color newColor) { - color = newColor; - repaint(); - } - - public Color getColor() { - return color; - } - - public boolean isColorChooserEnabled() { - return colorChooserEnabled; - } - - public void setColorChooserEnabled(boolean enabled) { - this.colorChooserEnabled = enabled; - } - - public void actionPerformed(ActionEvent e) { - if (!colorChooserEnabled) { - return; - } - - Color c = JColorChooser.showDialog(this, "Choose color", color); - if (c != null) { - setColor(c); - } - } - - class ColorBoxIcon implements Icon { - - public int getIconWidth() { - return ICON_SIZE.width; - } - - public int getIconHeight() { - return ICON_SIZE.height; - } - - public void paintIcon(Component c, Graphics g, int x, int y) { - Color oldColor = g.getColor(); - g.translate(x, y); - - g.setColor(color); - g.fillRect(0, 0, ICON_SIZE.width, ICON_SIZE.height); - - g.setColor(Color.black); - g.drawRect(0, 0, ICON_SIZE.width, ICON_SIZE.height); - - g.translate(-x, -y); - g.setColor(oldColor); - } - } -} - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/FlagsEditorPanel.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/FlagsEditorPanel.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,247 +0,0 @@ -package at.ssw.visualizer.cfg.preferences; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.Enumeration; -import java.util.StringTokenizer; -import javax.swing.Box; -import javax.swing.BoxLayout; -import javax.swing.DefaultListModel; -import javax.swing.JButton; -import javax.swing.JColorChooser; -import javax.swing.JComponent; -import javax.swing.JList; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.ListSelectionModel; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; - -/** - * - * @author Bernhard Stiftner - * @author Rumpfhuber Stefan - */ -public class FlagsEditorPanel extends JPanel implements ActionListener, - ListSelectionListener { - - FlagListModel listModel; - JList list; - ColorChooserButton colorButton; - JButton newButton; - JButton removeButton; - JButton upButton; - JButton downButton; - - - /** Creates a new instance of FlagsEditorPanel */ - public FlagsEditorPanel(String flagString) { - setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); - - listModel = new FlagListModel(flagString); - list = new JList(listModel); - list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - list.addListSelectionListener(this); - add(new JScrollPane(list)); - - add(Box.createHorizontalStrut(3)); - - Box buttonBox = new Box(BoxLayout.Y_AXIS); - buttonBox.add(colorButton = new ColorChooserButton()); - buttonBox.add(newButton = new JButton("New...")); - buttonBox.add(removeButton = new JButton("Remove")); - buttonBox.add(upButton = new JButton("Up")); - buttonBox.add(downButton = new JButton("Down")); - buttonBox.add(Box.createVerticalGlue()); - add(buttonBox); - layoutButtonContainer(buttonBox); - - colorButton.setColorChooserEnabled(false); - colorButton.addActionListener(this); - newButton.addActionListener(this); - removeButton.addActionListener(this); - upButton.addActionListener(this); - downButton.addActionListener(this); - - selectionChanged(-1); // no selection - } - - /** - * Ugly helper to make a nice layout for vertically aligned buttons. - */ - private static void layoutButtonContainer(JComponent buttonContainer) { - int width = 0; - int height = 0; - - for (int i=0; i= listModel.size()-1) { - return; - } - Object o = listModel.getElementAt(index); - listModel.removeElementAt(index); - listModel.insertElementAt(o, index+1); - } - } - - public void valueChanged(ListSelectionEvent e) { - if (e.getValueIsAdjusting()) { - return; // another event will be fired soon - } - selectionChanged(list.getSelectedIndex()); - } - - protected void selectionChanged(int index) { //index is -1 if there is no selection - colorButton.setEnabled(index >= 0); - removeButton.setEnabled(index >= 0); - upButton.setEnabled(index > 0); - downButton.setEnabled(index >= 0 && index < listModel.getSize()-1); - - if (index >= 0) { - FlagListItem item = (FlagListItem)listModel.elementAt(index); - colorButton.setColor(item.getColor()); - list.setSelectedIndex(index); - } else { - colorButton.setColor(getBackground()); - } - } - - protected void changeColor() { - int selectedIndex = list.getSelectedIndex(); - FlagListItem item = (FlagListItem)listModel.elementAt(selectedIndex); - Color c = JColorChooser.showDialog(this, "Choose color", item.getColor()); - - if (c != null) { - item.setColor(c); - colorButton.setColor(c); - } - } - - class FlagListModel extends DefaultListModel { - - public FlagListModel(String flagString) { - if (flagString != null) { - setFlagString(flagString); - } - } - - public String getFlagString() { - StringBuffer sb = new StringBuffer(); - Enumeration e = elements(); - while (e.hasMoreElements()) { - FlagListItem item = (FlagListItem)e.nextElement(); - sb.append(item.getFlagString()); - Color c = item.getColor(); - sb.append("(").append(c.getRed()).append(",").append(c.getGreen()).append(",").append(c.getBlue()).append(")"); - if (e.hasMoreElements()) { - sb.append(";"); - } - } - return sb.toString(); - } - - public void setFlagString(String flagString) { - clear(); - StringTokenizer st = new StringTokenizer(flagString, ";"); - while (st.hasMoreTokens()) { - String s = st.nextToken(); - String flag = s.split("\\(")[0]; - Color color = FlagsSetting.toColor(s); - addElement(new FlagListItem(flag, color)); - } - } - - } - - class FlagListItem { - - Color color; - String flagString; - - public FlagListItem(String flagString, Color color) { - this.flagString = flagString; - this.color = color; - } - - public Color getColor() { - return color; - } - - public String getFlagString() { - return flagString; - } - - public void setColor(Color c) { - color = c; - } - - @Override - public String toString() { - return flagString; - } - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/FlagsSetting.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/FlagsSetting.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -package at.ssw.visualizer.cfg.preferences; - -import java.awt.Color; -import java.io.Serializable; -import java.util.Hashtable; -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public class FlagsSetting implements Serializable { - - private Hashtable flag2color; - private Hashtable priority; - private String flagString; - - - public FlagsSetting(String flagString) { - this.flagString = flagString; - flag2color = new Hashtable<>(); - priority = new Hashtable<>(); - String[] flags = flagString.split(";"); - - int z = 0; - for(String s : flags) { - String flag = s.split("\\(")[0]; - Color c = toColor(s); - flag2color.put(flag, c); - priority.put(flag, z); - z++; - } - } - - public Color getColor(List strings) { - int minPriority = Integer.MAX_VALUE; - Color result = null; - - for(String s : strings) { - Color curColor = flag2color.get(s); - if(curColor != null) { - int curPriority = priority.get(s); - if(curPriority < minPriority) { - minPriority = curPriority; - result = curColor; - } - } - } - - return result; - } - - public static Color toColor(String s) { - String sArr[] = s.split("\\("); - String Color = sArr[1].substring(0, sArr[1].length() - 1); - String ColorArr[] = Color.split(","); - int r = Integer.parseInt(ColorArr[0]); - int g = Integer.parseInt(ColorArr[1]); - int b = Integer.parseInt(ColorArr[2]); - return new Color(r, g, b); - } - - public String getFlagString() { - return flagString; - } - - @Override - public boolean equals(Object o) { - if(o==null) - return false; - return this.toString().equals(o.toString()); - } - - @Override - public int hashCode() { - int hash = 7; - hash = 19 * hash + (this.flagString != null ? this.flagString.hashCode() : 0); - return hash; - } - - @Override - public String toString(){ - return "FlagSetting[" + flagString + "]"; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/FontChooserDialog.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/preferences/FontChooserDialog.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -package at.ssw.visualizer.cfg.preferences; - -import java.awt.Font; -import java.beans.PropertyEditor; -import java.beans.PropertyEditorManager; -import org.openide.DialogDescriptor; -import org.openide.DialogDisplayer; - -/** - * - * @author Bernhard Stiftner - */ -public class FontChooserDialog { - - /* - * Displays a font selection dialog. - * @return The selected font, or the initial font if the user chose - * to bail out - */ - public static Font show(Font initialFont) { - PropertyEditor pe = PropertyEditorManager.findEditor(Font.class); - if (pe == null) { - throw new RuntimeException("Could not find font editor component."); - } - pe.setValue(initialFont); - DialogDescriptor dd = new DialogDescriptor( - pe.getCustomEditor(), - "Choose Font"); - DialogDisplayer.getDefault().createDialog(dd).setVisible(true); - if (dd.getValue() == DialogDescriptor.OK_OPTION) { - Font f = (Font)pe.getValue(); - return f; - } - return initialFont; - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/BezierWidget.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/BezierWidget.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,345 +0,0 @@ -package at.ssw.visualizer.cfg.visual; - -import org.netbeans.api.visual.widget.ConnectionWidget; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.Shape; -import java.awt.Stroke; -import java.awt.geom.AffineTransform; -import java.awt.geom.CubicCurve2D; -import java.awt.geom.GeneralPath; -import java.awt.geom.Point2D; -import java.util.List; -import org.netbeans.api.visual.anchor.AnchorShape; -import org.netbeans.api.visual.graph.GraphScene; -import org.netbeans.api.visual.widget.Scene; -import org.netbeans.api.visual.widget.Widget; - - -/** - * In comparison to the default ConnectionWidget this class is able to connect - * Widgets with a curve instead of a straight line sequence. Between two control - * points a curve is painted as cubic bezier curve the control points are - * calculated automaticaly they depend on the position of the prior- and the - * following control points. - * In conjunction with a suitable router the connection will be a straight line - * or a curve depending on the amount and the position of the controlpoints. - * Controlpoints supplied by the router, are treated as curve intersection points. - * For Reflexive edges the router doesn`t need to supply controlpoints, they - * get painted by this class automatically. If the router supplys more as 2 - * control points for a recursive edge the edge gets painted with the default - * curve approximation algorithm. - */ -public class BezierWidget extends ConnectionWidget { - private static final double BEZIER_SCALE = 0.3; - private static final double ENDPOINT_DEVIATION = 3;//curve endpoint approximation accuracy - - private GraphScene scene=null; - - public BezierWidget(Scene scene) { - super(scene); - } - - public BezierWidget(GraphScene scene) { - super(scene); - this.scene=scene; - } - - - private boolean isReflexive(){ - return getSourceAnchor().getRelatedWidget() == getTargetAnchor().getRelatedWidget(); - } - - - @Override - protected Rectangle calculateClientArea() { - Rectangle bounds = null; - if(this.getControlPoints().size()>0){ - for(Point p : this.getControlPoints()){ - if(bounds==null) - bounds = new Rectangle(p); - else - bounds.add(p); - } - bounds.grow(5,5); - } - if(isReflexive()){ - Widget related = this.getTargetAnchor().getRelatedWidget(); - bounds = related.convertLocalToScene(related.getBounds()); - bounds.grow(10, 10); - } - if(bounds==null) - bounds = super.calculateClientArea(); - - return bounds; - } - - - - //returns prefered location for an edge -1 for left and 1 for right - private int edgeBalance(Widget nodeWidget) { - if(scene == null) - return 1; - - Point nodeLocation = nodeWidget.getLocation(); - int left = 0, right = 0; - - Object node = scene.findObject(nodeWidget); - - for(Object e : scene.findNodeEdges(node, true, true)) {//inputedges - ConnectionWidget cw = (ConnectionWidget) scene.findWidget(e); - - if(cw != this) { - Widget targetNodeWidget = cw.getTargetAnchor().getRelatedWidget(); - - Point location; - if(targetNodeWidget == nodeWidget) { - Widget sourceNodeWidget = cw.getSourceAnchor().getRelatedWidget(); - location = sourceNodeWidget.getLocation(); - } else { - location = targetNodeWidget.getLocation(); - } - - if(location.x < nodeLocation.x) - left++; - else - right++; - } - } - if(left < right) - return -1; - else - return 1; - } - - - - - /** - * if the edge is reflexive its painted as a cyclic edge - * if there are 2 controlpoints the connection is painted as a straight line from the source to the targetanchor - * if there are more as 2 controlpoints the connection path between 2 control points is painted as bezier curve - */ - - @Override - protected void paintWidget () { - - List contrPoints = this.getControlPoints(); - int listSize = contrPoints.size(); - - Graphics2D gr = getGraphics (); - - if (listSize <= 2) { - if(isReflexive()) { //special case for reflexive connection widgets - Widget related = this.getTargetAnchor().getRelatedWidget(); - int position = this.edgeBalance(related); - Rectangle bounds = related.convertLocalToScene(related.getBounds()); - gr.setColor (getLineColor()); - Point first = new Point(); - Point last = new Point(); - double centerX = bounds.getCenterX(); - first.x = (int) (centerX + bounds.width / 4); - first.y = bounds.y + bounds.height; - last.x = first.x; - last.y = bounds.y; - - gr.setStroke(this.getStroke()); - - double cutDistance = this.getTargetAnchorShape().getCutDistance(); - double anchorAngle = Math.PI/-3.0; - double cutX = Math.abs(Math.cos(anchorAngle)*cutDistance); - double cutY = Math.abs(Math.sin(anchorAngle)*cutDistance); - int ydiff=first.y-last.y; - int endy = -ydiff; - double height=bounds.getHeight(); - double cy = height/4.0; - double cx=bounds.getWidth()/5.0; - double dcx = cx*2; - GeneralPath gp = new GeneralPath(); - gp.moveTo(0, 0); - gp.quadTo(0, cy, cx, cy); - gp.quadTo(dcx, cy, dcx, -height/2.0); - gp.quadTo(dcx, endy - cy, cy, -(cy+ydiff)); - gp.quadTo(cutX*1.5, endy - cy, cutX, endy-cutY); - - AffineTransform af = new AffineTransform(); - AnchorShape anchorShape = this.getTargetAnchorShape(); - - if(position < 0) { - first.x = (int) (centerX - bounds.width / 4); - af.translate(first.x, first.y); - af.scale(-1.0, 1.0); - last.x = first.x; - } else { - af.translate(first.x, first.y); - } - Shape s = gp.createTransformedShape(af); - gr.draw(s); - - if (last != null) { - AffineTransform previousTransform = gr.getTransform (); - gr.translate (last.x, last.y); - - if(position < 0) - gr.rotate(Math.PI - anchorAngle); - else - gr.rotate (anchorAngle); - - anchorShape.paint (gr, false); - gr.setTransform (previousTransform); - } - - } else { - super.paintWidget(); - } - return; - } - - //bezier curve... - GeneralPath curvePath = new GeneralPath(); - Point lastControlPoint = null; - double lastControlPointRotation = 0.0; - - Point prev = null; - for (int i = 0; i < listSize - 1; i++) { - Point cur = contrPoints.get(i); - Point next = contrPoints.get(i + 1); - Point nextnext = null; - if (i < listSize - 2) { - nextnext = contrPoints.get(i + 2); - } - - double len = cur.distance(next); - double scale = len * BEZIER_SCALE; - Point bezierFrom = null;//first ControlPoint - Point bezierTo = null;//second ControlPoint - - if (prev == null) { - //first point - curvePath.moveTo(cur.x, cur.y);//startpoint - bezierFrom = cur; - } else { - bezierFrom = new Point(next.x - prev.x, next.y - prev.y); - bezierFrom = scaleVector(bezierFrom, scale); - bezierFrom.translate(cur.x, cur.y); - } - - if (nextnext == null) {//next== last point (curve to) - lastControlPoint=next; - bezierTo = next;//set 2nd intermediate point to endpoint - GeneralPath lastseg = this.subdivide(cur, bezierFrom, bezierTo, next); - if(lastseg != null) - curvePath.append(lastseg, true); - break; - } else { - bezierTo = new Point(cur.x - nextnext.x, cur.y - nextnext.y); - bezierTo = scaleVector(bezierTo, scale); - bezierTo.translate(next.x, next.y); - } - - curvePath.curveTo( - bezierFrom.x, bezierFrom.y,//controlPoint1 - bezierTo.x, bezierTo.y,//controlPoint2 - next.x,next.y - ); - prev = cur; - } - Point2D cur = curvePath.getCurrentPoint(); - Point next = lastControlPoint; - - lastControlPointRotation = //anchor anchorAngle - Math.atan2 (cur.getY() - next.y, cur.getX() - next.x); - - Color previousColor = gr.getColor(); - gr.setColor (getLineColor()); - Stroke s = this.getStroke(); - gr.setStroke(s); - gr.setColor(this.getLineColor()); - gr.draw(curvePath); - - AffineTransform previousTransform = gr.getTransform (); - gr.translate (lastControlPoint.x, lastControlPoint.y); - gr.rotate (lastControlPointRotation); - AnchorShape targetAnchorShape = this.getTargetAnchorShape(); - targetAnchorShape.paint (gr, false); - gr.setTransform (previousTransform); - - //paint ControlPoints if enabled - if (isPaintControlPoints()) { - int last = listSize - 1; - for (int index = 0; index <= last; index ++) { - Point point = contrPoints.get (index); - previousTransform = gr.getTransform (); - gr.translate (point.x, point.y); - if (index == 0 || index == last) - getEndPointShape().paint (gr); - else - getControlPointShape().paint (gr); - gr.setTransform (previousTransform); - } - - } - gr.setColor(previousColor); - } - - - - private GeneralPath subdivide (Point b0, Point b1, Point b2, Point b3) { - double cutDistance = getTargetAnchorShape().getCutDistance(); - double minDistance = cutDistance - ENDPOINT_DEVIATION; - /** - * if the cutDistance is valid the last segment of the curve - * gets reduced by subdivision until the distance of the endpoint(epDistance) - * satisfys the condition (cutDistance > epDistance > (cutDistance - ENDPOINT-DEVIATION) - */ - if(cutDistance > minDistance && minDistance > 0 ) { - GeneralPath path = new GeneralPath(); - - path.moveTo(b0.x, b0.y); - - CubicCurve2D.Double left = new CubicCurve2D.Double( - b0.x, b0.y, - b1.x, b1.y, - b2.x, b2.y, - b3.x, b3.y); - - CubicCurve2D right=new CubicCurve2D.Double(); - left.subdivide(left, right); - double distance = b3.distance(left.getP2()); - //if the distance is bigger as the cutDistance the left segment is added - //and the right segment is divided again - while(distance>cutDistance){ - path.append(left, true); - right.subdivide(left, right); - distance = b3.distance(left.getP2()); - //if the devision removed to much the left segment is divided - while(distance < minDistance) { - //changes the distance to ~ (distance+distance/2) - left.subdivide(left, right); - distance = b3.distance(left.getP2()); - } - } - //append the last segment with (minDistance < distance < cutDistance) - //actually we should check if the a division happend, but this is very unlikly - path.append(left, true); - return path; - } - return null; - } - - - - - - private static Point scaleVector(Point vector, double len) { - double scale = Math.sqrt(vector.x * vector.x + vector.y * vector.y); - if(scale==0.0) return vector; - scale = len / scale; - return new Point( - Math.round(vector.x * (float)scale), - Math.round(vector.y * (float)scale)); - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/PolylineRouter.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/PolylineRouter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,360 +0,0 @@ -package at.ssw.visualizer.cfg.visual; - -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.geom.Line2D; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import org.netbeans.api.visual.anchor.Anchor; -import org.netbeans.api.visual.router.Router; -import org.netbeans.api.visual.widget.ConnectionWidget; -import org.netbeans.api.visual.widget.Widget; - -/** - * Router Class with Collision Detection - * - * - * The returned path is a straight line there is no node widget between the source and the target node, - * if there are nodewidgets in between it tries to find a path around those abstacles to avoid collisions. - * The algorithm for the search of this path is limited by a fixed number of iterations defined in - * NUMER_OF_ITERATIONS to return a result in reasonable time. If the calculation exceeds this limit the - * path returned contains at least 1 collision with a nodewidget. - */ - -public class PolylineRouter implements Router { - private static final float FACTOR = 0.70f; - - private static final int HEXPAND = 3; - private static final int VEXPAND = 3; - private static final int NUMBER_OF_ITERATIONS = 8; - - WidgetCollisionCollector collector; - - - public PolylineRouter(WidgetCollisionCollector collector){ - this.collector=collector; - } - - - public List routeConnection(final ConnectionWidget widget) { - if(!widget.isVisible()) return Collections.emptyList(); - - Anchor sourceAnchor = widget.getSourceAnchor(); - Anchor targetAnchor = widget.getTargetAnchor(); - - if(sourceAnchor == null || targetAnchor == null) - return null; - - Point start = sourceAnchor.compute(widget.getSourceAnchorEntry()).getAnchorSceneLocation(); - Point end = targetAnchor.compute(widget.getTargetAnchorEntry()).getAnchorSceneLocation(); - - Widget sourceWidget = sourceAnchor.getRelatedWidget(); - Widget targetWidget = targetAnchor.getRelatedWidget(); - - - if(sourceWidget == targetWidget){//reflexive edges doesnt need any path - return Collections.emptyList(); - } - - List nodeWidgets = new ArrayList<>(); - - if(collector != null){ - collector.collectCollisions(nodeWidgets); - //source and target widget are not treatet as obstacle - nodeWidgets.remove(sourceWidget); - nodeWidgets.remove(targetWidget); - } - - List controlPoints = optimize(nodeWidgets, widget, start, end); - - //size==2 => straight line - //size==3 => ensures a collision between cp0 and cp2 therefore its not possible to simplify it - if(controlPoints.size() > 3) - controlPoints = simplify(nodeWidgets, controlPoints); - - return controlPoints; - } - - - private List simplify(Collection nodeWidgets, List list) { - List result = new ArrayList<>(); - result.add( list.get(0) );//add startpoint - for (int i = 1; i < list.size(); i++) { - Point prev = list.get(i - 1); - for (int j = i; j < list.size(); j++) { - Point cur = list.get(j); - if (!intersects(nodeWidgets, prev, cur)) { - i = j; - } - } - result.add(list.get(i)); - } - return result; - } - - /** - * Computates the Anchorposition like the Rectangular anchor for a - * given widget as source/target and a controlpoint as opposit anchorposition - */ - - private Point computateAnchorPosition(Widget relatedWidget, Point controlPoint) { - Rectangle bounds = relatedWidget.getBounds(); - Point relatedLocation = relatedWidget.getLocation();//center of the widget - - if (bounds.isEmpty () || relatedLocation.equals (controlPoint)) - return relatedLocation; - - float dx = controlPoint.x - relatedLocation.x; - float dy = controlPoint.y - relatedLocation.y; - - float ddx = Math.abs (dx) / (float) bounds.width; - float ddy = Math.abs (dy) / (float) bounds.height; - - float scale = 0.5f / Math.max (ddx, ddy); - - Point point = new Point (Math.round (relatedLocation.x + scale * dx), - Math.round (relatedLocation.y + scale * dy)); - return point; - } - - - - private List optimize(Collection nodeWidgets, ConnectionWidget connWidget, Point start, Point end) { - - List list = new ArrayList<>(); - list.add(start); - list.add(end); - - boolean progress = true; - - for (int j = 0; progress && j < NUMBER_OF_ITERATIONS ; j++) { - progress = false; - List newList = new ArrayList<>(); - for (int i = 0; i < list.size() - 1 ; i++) { - Point cur = list.get(i); - Point next = list.get(i + 1); - newList.add(cur); - List intermediate = optimizeLine(nodeWidgets, cur, next); - if (intermediate != null && intermediate.size() > 0) { - progress = true; - newList.addAll(intermediate);//insert new controlpoints between cur and next - } - } - newList.add(list.get(list.size()-1));//add endpoint of the polyline - list = newList; - - } - - if(list.size() > 2) { - Widget sourceNode = connWidget.getSourceAnchor().getRelatedWidget(); - Widget targetNode = connWidget.getTargetAnchor().getRelatedWidget(); - Rectangle sourceBounds = sourceNode.convertLocalToScene(sourceNode.getBounds()); - Rectangle targetBounds = targetNode.convertLocalToScene(targetNode.getBounds()); - sourceBounds.grow(HEXPAND, VEXPAND); - - /** - * add only points which are not intersecting the source and the target - * widget bounds caused by invalid bad anchor positions. The first - * and the last point is ignored cause the anchor is recalculated - * anyway. - */ - ArrayList tmp = new ArrayList<>(); - int listSize=list.size(); - tmp.add(list.get(0)); - int i=0; - while(++i < listSize-1) { - Point p = list.get(i); - if(!sourceBounds.contains(p) || !targetBounds.contains(p)) - tmp.add(p); - } - - tmp.add(list.get(i)); - if(tmp.size() < 3) - return tmp; - - list=tmp; - //calculate a proper anchor position using the second/penultimate controlpoint for start/end - start = this.computateAnchorPosition(connWidget.getSourceAnchor().getRelatedWidget(), list.get(1)); - end = this.computateAnchorPosition(connWidget.getTargetAnchor().getRelatedWidget(), list.get(list.size()-2)); - list.set(0,start); - list.set(list.size()-1, end); - } - return list; - } - - - /** - * trys to optimize a line from p1 to p2 to avoid collisions with node widgets - * returns null if the line doesn`t intersect with any nodewidget - * or a list with immediate points between p1 and p2 to avoid collisions - */ - private List optimizeLine(Collection nodeWidgets, Point p1, Point p2) { - Line2D line = new Line2D.Double(p1, p2); - - for(Widget w : nodeWidgets ) { - if( w.isVisible() ) { - Rectangle r = w.convertLocalToScene(w.getBounds()); - r.grow(HEXPAND, VEXPAND); - - if (!line.intersects(r)) continue; - - Point location = w.getLocation(); - int distx = (int) (r.width * FACTOR); - int disty = (int) (r.height * FACTOR); - - int minIntersects = Integer.MAX_VALUE; - int min = Integer.MAX_VALUE; - List minSol = null; - for (int i = -1; i <= 1; i++) { - for (int j = -1; j <= 1; j++) { - if (i != 0 || j != 0) { - Point cur = new Point(location.x + i * distx, location.y + j * disty); - List list1 = new ArrayList<>(); - list1.add(p1); - list1.add(cur); - list1.add(p2); - int crossProd = Math.abs(crossProduct(p1, cur, p2)); - if (!intersects(w, list1)) { - Line2D line1 = new Line2D.Float(p1, cur); - Line2D line2 = new Line2D.Float(p2, cur); - int curIntersects = this.countNodeIntersections(nodeWidgets, line1, line2); - - if (curIntersects < minIntersects - || (curIntersects == minIntersects && crossProd < min)) { - minIntersects = curIntersects; - min = crossProd; - minSol = new ArrayList<>(); - minSol.add(cur); - } - } - - if (i == 0 || j == 0) { - Point cur1, cur2; - if (i == 0) { - cur1 = new Point(location.x + distx/2, location.y + j * disty); - cur2 = new Point(location.x - distx/2, location.y + j * disty); - } else { // (j == 0) - cur1 = new Point(location.x + i * distx, location.y + disty/2); - cur2 = new Point(location.x + i * distx, location.y - disty/2); - } - - Point vec1 = new Point(p1.x - cur1.x, p1.y - cur1.y); - int offset1 = vec1.x * vec1.x + vec1.y * vec1.y; - - Point vec2 = new Point(p1.x - cur2.x, p1.y - cur2.y); - int offset2 = vec2.x * vec2.x + vec2.y * vec2.y; - - if (offset2 < offset1) { - Point tmp = cur1; - cur1 = cur2; - cur2 = tmp; - } - - List list2 = new ArrayList<>(); - list2.add(p1); - list2.add(cur1); - list2.add(cur2); - list2.add(p2); - - int cross1 = crossProduct(p1, cur1, cur2); - int cross2 = crossProduct(cur1, cur2, p2); - - if (cross1 > 0) { - cross1 = 1; - } else if (cross1 < 0) { - cross1 = -1; - } - - if (cross2 > 0) { - cross2 = 1; - } else if (cross2 < 0) { - cross2 = -1; - } - if ((cross1 == cross2 || cross1 == 0 || cross2 == 0) && !intersects(w, list2)) { - Line2D line1 = new Line2D.Float(p1, cur1); - Line2D line2 = new Line2D.Float(cur1, cur2); - Line2D line3 = new Line2D.Float(p2, cur2); - int curIntersects = this.countNodeIntersections(nodeWidgets, line1, line2, line3); - - // This is a bit better - crossProd--; - - if (curIntersects < minIntersects - || (curIntersects == minIntersects && crossProd < min)) { - minIntersects = curIntersects; - min = crossProd; - minSol = new ArrayList<>(); - minSol.add(cur1); - minSol.add(cur2); - } - } - } - } - } - } - if (minSol != null) { - return minSol; - } - } - } - return null; - } - - - - private int countNodeIntersections(Collection nodeWidgets, Line2D... lines){ - int count=0; - for(Widget nw : nodeWidgets){ - if(nw.isVisible()) { - Rectangle bounds = nw.convertLocalToScene(nw.getBounds()); - for( Line2D line : lines){ - if(line.intersects(bounds)) - count++; - } - } - } - return count; - } - - - private boolean intersects(Collection nodeWidgets, Point start, Point end) { - List pointlist = new ArrayList<>(); - pointlist.add(start); - pointlist.add(end); - - for(Widget w : nodeWidgets){ - if(w.isVisible() && intersects(w, pointlist)) { - return true; - } - } - return false; - } - - - private boolean intersects(Widget w, List list) { - Rectangle r = w.convertLocalToScene(w.getBounds()); - r.grow(HEXPAND, VEXPAND); - return intersects(list, r); - } - - - private boolean intersects(List list, Rectangle rect){ - for(int i=1; i < list.size(); i++) { - Point cur = list.get(i-1); - Point next = list.get(i); - if(rect.intersectsLine(cur.x, cur.y, next.x, next.y)) - return true; - } - return false; - } - - - private int crossProduct(Point p1, Point p2, Point p3) { - Point off1 = new Point(p1.x - p2.x, p1.y - p2.y); - Point off2 = new Point(p3.x - p2.x, p3.y - p2.y); - return (off1.x * off2.y - off1.y * off2.x); - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/PolylineRouterV2.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/PolylineRouterV2.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,393 +0,0 @@ -package at.ssw.visualizer.cfg.visual; - -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.geom.Line2D; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import org.netbeans.api.visual.anchor.Anchor; -import org.netbeans.api.visual.router.Router; -import org.netbeans.api.visual.widget.ConnectionWidget; -import org.netbeans.api.visual.widget.Widget; - -/** - * Router Class with Collision Detection - * - * - * The returned path is a straight line there is no node widget between the source and the target node, - * if there are nodewidgets in between it tries to find a path around those abstacles to avoid collisions. - * The algorithm for the search of this path is limited by a fixed number of iterations defined in - * NUMER_OF_ITERATIONS to return a result in reasonable time. If the calculation exceeds this limit the - * path returned contains at least 1 collision with a nodewidget. - * - * This class intend to solve the same problem as the class PolyLineRouter but - * uses slightly different methods. - * + uses another algorithm for solving the collision. - * + the obstacle bounds are calulated in advance to avoid a recalculation. - * - there is no heuristic, the shortest path around the widget is choosen asap. - * - * - * - */ - -public class PolylineRouterV2 implements Router { - private static final int HEXPAND = 3; - private static final int VEXPAND = 3; - private static final int NUMBER_OF_ITERATIONS = 8; - - WidgetCollisionCollector collector; - - - public PolylineRouterV2(WidgetCollisionCollector collector){ - this.collector=collector; - } - - - public List routeConnection(final ConnectionWidget widget) { - if(!widget.isVisible()) return Collections.emptyList(); - - Anchor sourceAnchor = widget.getSourceAnchor(); - Anchor targetAnchor = widget.getTargetAnchor(); - - if(sourceAnchor == null || targetAnchor == null) - return null; - - Point start = sourceAnchor.compute(widget.getSourceAnchorEntry()).getAnchorSceneLocation(); - Point end = targetAnchor.compute(widget.getTargetAnchorEntry()).getAnchorSceneLocation(); - - Widget sourceWidget = sourceAnchor.getRelatedWidget(); - Widget targetWidget = targetAnchor.getRelatedWidget(); - - - if(sourceWidget == targetWidget){//reflexive edges doesnt need any path - return Collections.emptyList(); - } - - - Point srcCenter = this.getSceneLocation(sourceWidget); - Point tarCenter = this.getSceneLocation(targetWidget); - - List widgetObstacles = new ArrayList<>(); - - if(collector != null){ - collector.collectCollisions(widgetObstacles); - } - - List obstacles = new ArrayList<>(widgetObstacles.size()); - this.collectObstacles(obstacles, widgetObstacles, widget); - - - List controlPoints = optimize(obstacles, srcCenter, tarCenter); -// size==2 => straight line -// size==3 => ensures a collision between cp0 and cp2 therefore its not possible to simplify it - if(controlPoints.size() > 3){ - Point rstart = this.computateAnchorPosition(sourceWidget, controlPoints.get(1)); - Point rend = this.computateAnchorPosition(targetWidget, controlPoints.get(controlPoints.size()-2)); - controlPoints.set(0, rstart); - controlPoints.set(controlPoints.size()-1, rend); - controlPoints = simplify(obstacles, controlPoints); - } else if (controlPoints.size()>=2){ - //use old points - controlPoints.set(0, start); - controlPoints.set(controlPoints.size()-1, end); - - } - return controlPoints; - } - - - private int collectObstacles(List colrects, List colwidgets , ConnectionWidget cw){ - int count=0; - Anchor sourceAnchor = cw.getSourceAnchor(); - Anchor targetAnchor = cw.getTargetAnchor(); - Widget sourceWidget = sourceAnchor.getRelatedWidget(); - Widget targetWidget = targetAnchor.getRelatedWidget(); - Point start = sourceAnchor.compute(cw.getSourceAnchorEntry()).getAnchorSceneLocation(); - Point end = targetAnchor.compute(cw.getTargetAnchorEntry()).getAnchorSceneLocation(); - - for(Widget w : colwidgets){ - - if(w==sourceWidget || w == targetWidget) continue; - - Rectangle r = w.convertLocalToScene(w.getBounds()); - r.grow(HEXPAND, VEXPAND); - if(r.intersectsLine(start.x,start.y,end.x,end.y)) - count++; - colrects.add(r); - } - return count; - } - - - private Point center (Rectangle bounds) { - return new Point (bounds.x + bounds.width / 2, bounds.y + bounds.height / 2); - } - - /** - * Returns the scene location of a related widget. - * bounds might be null if the widget was not added to the scene - * @return the scene location; null if no related widget is assigned - */ - public Point getSceneLocation (Widget relatedWidget) { - if (relatedWidget != null) { - Rectangle bounds = relatedWidget.getBounds (); - if(bounds != null) - return center(relatedWidget.convertLocalToScene(bounds)); - } - return null; - } - - /** - * Computates the Anchorposition like the Rectangular anchor for a - * given widget as source/target and a controlpoint as opposit anchorposition - */ - - private Point computateAnchorPosition(Widget relatedWidget, Point controlPoint) { - Rectangle bounds = relatedWidget.getBounds(); - - //todo: fix, center of widget must be cacluated trough the bounds - //since there are some wheird widgets where the location is not the center of the widget - Point relatedLocation = relatedWidget.getLocation();//center of the widget - - if (bounds.isEmpty () || relatedLocation.equals (controlPoint)) - return relatedLocation; - - float dx = controlPoint.x - relatedLocation.x; - float dy = controlPoint.y - relatedLocation.y; - - float ddx = Math.abs (dx) / (float) bounds.width; - float ddy = Math.abs (dy) / (float) bounds.height; - - float scale = 0.5f / Math.max (ddx, ddy); - - Point point = new Point (Math.round (relatedLocation.x + scale * dx), - Math.round (relatedLocation.y + scale * dy)); - return point; - } - - private List simplify(List obstacles, List list) { - List result = new ArrayList<>(list.size()); - result.add( list.get(0) );//add startpoint - for (int i = 1; i < list.size(); i++) { - Point prev = list.get(i - 1); - for (int j = i; j < list.size(); j++) { - Point cur = list.get(j); - if (!intersects(obstacles, prev, cur)) { - i = j; - } - } - result.add(list.get(i)); - } - return result; - } - - private List optimize(List nodeWidgets, Point start, Point end) { - - List list = new ArrayList<>(); - list.add(start); - list.add(end); - - boolean progress = true; - - for (int j = 0; progress && j < NUMBER_OF_ITERATIONS ; j++) { - progress = false; - List newList = new ArrayList<>(); - for (int i = 0; i < list.size() - 1 ; i++) { - Point cur = list.get(i); - Point next = list.get(i + 1); - newList.add(cur); - List intermediate = optimizeLine(nodeWidgets, cur, next); - if (intermediate != null && intermediate.size() > 0) { - progress = true; - newList.addAll(intermediate);//insert new controlpoints between cur and next - } - } - newList.add(list.get(list.size()-1));//add endpoint of the polyline - list = newList; - - } - - return list; - } - - - /** - * trys to optimize a line from p1 to p2 to avoid collisions with rectangles - * returns null if the line doesn`t intersect with any nodewidget or - * if the obstacles are overlapping - * ---------------------------------------------------------------------- - * if the collision is solved it returns a list with immediate points - * between p1 and p2. The points are taken from hull points of and grown - * rectangle. - */ - private List optimizeLine(List obstacles, Point p1, Point p2) { - Line2D line = new Line2D.Double(p1, p2); - boolean inbounds=false; - Rectangle ibr=null; - ArrayList sol = new ArrayList<>(); - boolean leftIntersection; - boolean rightIntersection; - boolean bottomIntersection; - boolean topIntersection; - Point interLeft=new Point(); - Point interRight=new Point(); - Point interBot=new Point(); - Point interTop=new Point(); - - - - for(Rectangle r : obstacles ) { - if (!line.intersects(r)) continue; - - int w=r.width+2; - int h=r.height+2; - Point topLeft = r.getLocation(); - topLeft.x-=1; - topLeft.y-=1; - Point topRight = new Point(topLeft.x+w, topLeft.y); - Point bottomLeft = new Point(topLeft.x, topLeft.y+h); - Point bottomRight = new Point(topRight.x, bottomLeft.y); - leftIntersection = findIntersectionPoint(p1, p2, topLeft, bottomLeft, interLeft); - rightIntersection = findIntersectionPoint(p1, p2, topRight, bottomRight, interRight); - bottomIntersection = findIntersectionPoint(p1, p2, bottomLeft, bottomRight, interBot); - topIntersection = findIntersectionPoint(p1, p2, topLeft, topRight, interTop); - - //Intersection points are not used yet. This could be actually a - //good approach to avoid additional collisions because it would be - //still the same vector. - - if(leftIntersection) { - if(topIntersection) {//left and top - sol.add(topLeft); - } - else if(bottomIntersection){//left and bottom - sol.add(bottomLeft); - } - else if(rightIntersection){//left and right - double disttl = topLeft.distance(p1); - double distbl = bottomLeft.distance(p1); - if(disttl > distbl){ - //pass at the bottom - double distbr = bottomRight.distance(p1); - if(distbl < distbr){ - //from the left to the right - sol.add(bottomLeft); - sol.add(bottomRight); - } else { - //from the right to the left - sol.add(bottomRight); - sol.add(bottomLeft); - } - } else { - //pass at the top - double disttr = topRight.distance(p1); - if(disttl < disttr){ - //from the left to the right - sol.add(topLeft); - sol.add(topRight); - } else { - //from the right to the left - sol.add(topRight); - sol.add(topLeft); - } - } - } else {//only left => inside bounds - inbounds=true; - } - } else if (rightIntersection) { - if(topIntersection) {//right and top - sol.add(topRight); - } - else if(bottomIntersection){//right and bottom - sol.add(bottomRight); - } else { //only right => inside the bounds - inbounds=true; - } - } else if (topIntersection && bottomIntersection) {//top and bottom - double disttop = interTop.distance(p1); - double distbot = interBot.distance(p1); - if(disttop < distbot ){ - //from the top to the bottom - double distleft = interTop.distance(topLeft); - double distright = interTop.distance(topRight); - if(distleft < distright){ - //pass left - sol.add(topLeft); - sol.add(bottomLeft); - } else { - //pass right - sol.add(topRight); - sol.add(bottomRight); - } - } else { - //from the bottom to the top - double distleft = interBot.distance(bottomLeft); - double distright = interBot.distance(bottomRight); - if(distleft < distright){ - //pass left - sol.add(bottomLeft); - sol.add(topLeft); - } else { - //pass right - sol.add(bottomRight); - sol.add(topRight); - } - } - } else {//only bottom or only top - inbounds=true; - } /* ENDIF */ - - //breakpoint <-- collision detected - - if(sol.size()>0) {//solution found - assert(!inbounds); - return sol; - } else { //no solution found=> inbounds - assert(inbounds); - assert(sol.size()==0); - //handle collision or just skip it and search for the next collisionj - ibr=r; - //jump out of the loop to able to interate over the obstacles - break; - } - }/* end foreach obstacle */ - - if(inbounds || ibr != null){ - assert(inbounds); - assert(ibr!=null); - } - return null;//no collison found - }/* end optimizeLine */ - - - - //check intersection between line p0->p1 for a given set of obstacles - private static boolean intersects(List obstacles, Point p0, Point p1) { - for(Rectangle r : obstacles){ - if(r.intersectsLine(p0.x, p0.y, p1.x, p1.y)) - return true; - } - return false; - } - - - private boolean findIntersectionPoint( - Point p0, Point p1, Point p2, Point p3, Point pI) { - float q = (p0.y - p2.y)*(p3.x - p2.x) - (p0.x - p2.x)*(p3.y - p2.y); - float d = (p1.x - p0.x)*(p3.y - p2.y) - (p1.y - p0.y)*(p3.x - p2.x); - - //parallel ? - if(d==0) return false; - - float r = q / d; - q = (p0.y - p2.y)*(p1.x - p0.x) - (p0.x - p2.x)*(p1.y - p0.y); - - float s = q / d; - if(r<0 || r>1 || s<0 || s>1) return false; - - pI.x = p0.x + (int) (0.5f + r * (p1.x - p0.x)); - pI.y = p0.y + (int) (0.5f + r * (p1.y - p0.y)); - return true; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/SplineConnectionWidget.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/SplineConnectionWidget.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,541 +0,0 @@ -package at.ssw.visualizer.cfg.visual; - -import org.netbeans.api.visual.widget.ConnectionWidget; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.Shape; -import java.awt.geom.AffineTransform; -import java.awt.geom.CubicCurve2D; -import java.awt.geom.GeneralPath; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; -import java.util.List; -import org.netbeans.api.visual.anchor.AnchorShape; -import org.netbeans.api.visual.graph.GraphScene; -import org.netbeans.api.visual.widget.Scene; -import org.netbeans.api.visual.widget.Widget; - - -/** - * In comparison to the default ConnectionWidget this class is able to connect - * widgets with a curve instead of a straight line sequence. - * In conjunction with a suitable router the connection will be a straight line - * or a curve depending on the amount and the position of the controlpoints. - * Controlpoints supplied by the router, are treated as curve intersection points. - * For Reflexive edges the router doesn`t necessarily need to supply - * any controlpoints, they get painted by this automatically, this can be - * excepted if the router supplys more as 2 control points for a self edge, - * then the edge gets painted with the default curve interpolation algorithm. - * The method used for drawing curves uses a piecewise cubic interpolation - * algorithm. Between two control points a curve is painted as cubic bezier - * curve the, inner bezier points are calculated automatically with FMILL - * tangents and a chord parametrization, this interpolant is also known as - * cutmull-rom spline. The resulting spline fullfills c^1 continuity. - * The the end points the interpolation algorithm uses the bessel end condition. - */ - -public class SplineConnectionWidget extends ConnectionWidget { - private static final double ENDPOINT_DEVIATION = 3;//curve endpoint approximation accuracy - private static final double HIT_DISTANCE_SQUARE = 4.0;//distance for intersection test - private GraphScene scene=null; - private Point2D [] bezierPoints = null; - - public SplineConnectionWidget(Scene scene) { - super(scene); - if(scene instanceof GraphScene) - this.scene=(GraphScene) scene; - } - - //check for self - edge - private boolean isReflexive(){ - return getSourceAnchor().getRelatedWidget() == getTargetAnchor().getRelatedWidget(); - } - - - @Override - protected Rectangle calculateClientArea() { - - Rectangle bounds = null; - - if(this.getControlPoints().size()>2){ - bezierPoints = createBezierPoints(getControlPoints()); - } - //minmax method - returns the smallest bounding rectangle - //Curves and surfaces for CAGD (3rd ed.), p.54 - //exact calculation of the bounding min rect - if(bezierPoints != null) { - Rectangle2D bounds2D = null; - for (int i = 0; i < bezierPoints.length; i++) { - Point2D point = bezierPoints[i]; - if(bounds2D==null) - bounds2D = new Rectangle2D.Double(point.getX(),point.getY(),0,0); - else - bounds2D.add(point); - } - bounds = bounds2D.getBounds(); - bounds.grow(2, 2); - - } else if (getControlPoints().size()>0){ - for(Point p : this.getControlPoints()){ - if(bounds==null) - bounds = new Rectangle(p); - else - bounds.add(p); - } - bounds.grow(5,5); - - } else if (isReflexive()) { - Widget related = this.getTargetAnchor().getRelatedWidget(); - bounds = related.convertLocalToScene(related.getBounds()); - bounds.grow(10, 10); - } - - if(bounds==null) - bounds = super.calculateClientArea(); - - return bounds; - } - - - /** - * if the edge is reflexive its painted as a cyclic self edge, if there - * are two controlpoints the connection is painted as a straight line from - * the source to the targetanchor, if there are more as 2 controlpoints the - * connection path between two control points is painted as cutmull rom - * spline with bessel end tangents. - */ - @Override - protected void paintWidget () { - List contrPoints = this.getControlPoints(); - int listSize = contrPoints.size(); - - Graphics2D gr = getGraphics (); - - if (listSize <= 2) { - this.bezierPoints=null;//set bezier Points null for calulateClientArea() - if(isReflexive()) { //special case for reflexive connection widgets - this.drawReflexive(gr); - } else { - super.paintWidget(); - } - return; - } - - //bezier curve... listSize > 2 - GeneralPath curvePath = new GeneralPath(); - double lastControlPointRotation = 0.0; - - - Point2D [] bezPoints = this.createBezierPoints(contrPoints); - curvePath.moveTo(bezPoints[0].getX(), bezPoints[0].getY());//b00 - - //last segment is added by subdivision thats why its -5 - for (int i = 1; i < bezPoints.length-5; i+=3) { - curvePath.curveTo( - bezPoints[i].getX(), bezPoints[i].getY(),//b1i - bezPoints[i+1].getX(), bezPoints[i+1].getY(),//b2i - bezPoints[i+2].getX(), bezPoints[i+2].getY());//b3i - - } - - GeneralPath lastseg = subdivide2D( - bezPoints[bezPoints.length-4], - bezPoints[bezPoints.length-3], - bezPoints[bezPoints.length-2], - bezPoints[bezPoints.length-1]); - - - if(lastseg != null) - curvePath.append(lastseg, true); - - Point2D cur = curvePath.getCurrentPoint(); - Point lastControlPoint = contrPoints.get(listSize-1); - - lastControlPointRotation = //anchor anchorAngle - Math.atan2 (cur.getY() - lastControlPoint.y, cur.getX() - lastControlPoint.x); - - gr.setStroke(getStroke()); - gr.setColor(getLineColor()); - gr.draw(curvePath); - - - AffineTransform previousTransform = gr.getTransform (); - gr.translate (lastControlPoint.x, lastControlPoint.y); - gr.rotate (lastControlPointRotation); - AnchorShape targetAnchorShape = this.getTargetAnchorShape(); - targetAnchorShape.paint (gr, false); - gr.setTransform (previousTransform); - - //paint ControlPoints if enabled - if (isPaintControlPoints()) { - int last = listSize - 1; - for (int index = 0; index <= last; index ++) { - Point point = contrPoints.get (index); - previousTransform = gr.getTransform (); - gr.translate (point.x, point.y); - if (index == 0 || index == last) - getEndPointShape().paint (gr); - else - getControlPointShape().paint (gr); - gr.setTransform (previousTransform); - } - - } - } - - private void drawReflexive(Graphics2D gr){ - Widget related = this.getTargetAnchor().getRelatedWidget(); - int position = this.edgeBalance(related); - Rectangle bounds = related.convertLocalToScene(related.getBounds()); - gr.setColor (getLineColor()); - Point first = new Point(); - Point last = new Point(); - double centerX = bounds.getCenterX(); - first.x = (int) (centerX + bounds.width / 4); - first.y = bounds.y + bounds.height; - last.x = first.x; - last.y = bounds.y; - - gr.setStroke(this.getStroke()); - - double cutDistance = this.getTargetAnchorShape().getCutDistance(); - double anchorAngle = Math.PI/-3.0; - double cutX = Math.abs(Math.cos(anchorAngle)*cutDistance); - double cutY = Math.abs(Math.sin(anchorAngle)*cutDistance); - int ydiff=first.y-last.y; - int endy = -ydiff; - double height=bounds.getHeight(); - double cy = height/4.0; - double cx=bounds.getWidth()/5.0; - double dcx = cx*2; - GeneralPath gp = new GeneralPath(); - gp.moveTo(0, 0); - gp.quadTo(0, cy, cx, cy); - gp.quadTo(dcx, cy, dcx, -height/2.0); - gp.quadTo(dcx, endy - cy, cy, -(cy+ydiff)); - gp.quadTo(cutX*1.5, endy - cy, cutX, endy-cutY); - - AffineTransform af = new AffineTransform(); - AnchorShape anchorShape = this.getTargetAnchorShape(); - - if(position < 0) { - first.x = (int) (centerX - bounds.width / 4); - af.translate(first.x, first.y); - af.scale(-1.0, 1.0); - last.x = first.x; - } else { - af.translate(first.x, first.y); - } - Shape s = gp.createTransformedShape(af); - gr.draw(s); - - if (last != null) { - AffineTransform previousTransform = gr.getTransform (); - gr.translate (last.x, last.y); - - if(position < 0) - gr.rotate(Math.PI - anchorAngle); - else - gr.rotate (anchorAngle); - - anchorShape.paint (gr, false); - gr.setTransform (previousTransform); - } - } - - //returns prefered location for an edge -1 for left and 1 for right - private int edgeBalance(Widget nodeWidget) { - if(scene == null) - return 1; - - Point nodeLocation = nodeWidget.getLocation(); - int left = 0, right = 0; - - Object node = scene.findObject(nodeWidget); - - for(Object e : scene.findNodeEdges(node, true, true)) {//inputedges - ConnectionWidget cw = (ConnectionWidget) scene.findWidget(e); - - if(cw != this) { - Widget targetNodeWidget = cw.getTargetAnchor().getRelatedWidget(); - - Point location; - if(targetNodeWidget == nodeWidget) { - Widget sourceNodeWidget = cw.getSourceAnchor().getRelatedWidget(); - location = sourceNodeWidget.getLocation(); - } else { - location = targetNodeWidget.getLocation(); - } - - if(location.x < nodeLocation.x) - left++; - else - right++; - } - } - if(left < right) - return -1; - else - return 1; - } - - - private Point2D[] createBezierPoints(List list){ - if(list.size()<3) return null ; - - - int lastIdx = list.size()-1; - - - //chord length parametrization - double[] uis = new double[list.size()]; - uis[0]=0; - uis[1] = list.get(1).distance(list.get(0)); - for (int i = 1; i < uis.length; i++) { - Point cur = list.get(i); - Point prev = list.get(i-1); - uis[i]=uis[i-1]+ cur.distance(prev); - } - - - for (int i = 1; i < uis.length; i++) { - uis[i] /= uis[lastIdx]; - - } - double[] delta = new double[uis.length-1]; - for (int i = 0; i < delta.length; i++) { - double ui = uis[i]; - double uin = uis[i+1]; - delta[i] = uin-ui; - } - - - //FMILL tangent directions (chord length) - Point2D[] tangents = new Point2D[list.size()]; - - for (int i = 1; i < list.size()-1; i++) { - Point xBefore = list.get(i-1); - Point xAfter = list.get(i+1); - Point2D.Double tangent = new Point2D.Double (xAfter.x - xBefore.x, xAfter.y - xBefore.y); - tangents[i] = tangent; - } - - - Point2D [] bezPoints = new Point2D[(list.size()-1)*2+list.size()]; - //Catmull-Rom - for (int i = 1; i < list.size()-1; i++) { - Point b3i = list.get(i); - Point2D b3ib = b3iBefore(b3i, delta[i-1], delta[i], tangents[i]); - Point2D b3ia = b3iAfter(b3i, delta[i-1], delta[i], tangents[i]); - bezPoints[3*i] = b3i; - bezPoints[3*i-1] = b3ib; - bezPoints[3*i+1] = b3ia; - } - bezPoints[0] = list.get(0); - bezPoints[bezPoints.length-1] = list.get(list.size()-1); - - Point p0 = list.get(0); - Point p1 = list.get(1); - Point p2 = list.get(2); - Point pL_2 = list.get(lastIdx-2); - Point pL_1 = list.get(lastIdx-1); - Point pL = list.get(lastIdx); - - Point2D m1 = besselTangent(delta[0], delta[1], p0, p1, p2); - Point2D m0 = besselEndTangent(p0, p1, delta[0], m1); - - Point2D mLb = besselTangent(delta[delta.length-2], delta[delta.length-1], - pL_2,pL_1, pL); - Point2D mL = besselEndTangent(pL_1, pL, delta[delta.length-1], mLb); - - Point2D scaleM0 = scale(normalize(m0), p0.distance(p1));//increase distx/distxl to make curve rounder at the end - Point2D scaleML = scale(normalize(mL), pL.distance(pL_1)); - //Catmull-Rom for bessel points - Point2D b30a = b3iAfter(p0, delta[0], delta[0],scaleM0); - Point2D b33b = b3iBefore(pL, delta[delta.length-1], delta[delta.length-1],scaleML); - - bezPoints[1] = b30a; - bezPoints[bezPoints.length-2] = b33b; - - return bezPoints; - } - - - - private static Point2D besselTangent(double delta_ib, double delta_i, Point2D p0, Point2D p1 , Point2D p2){ - double alpha_i = delta_ib/(delta_ib+delta_i); - - double x = (1-alpha_i)/delta_ib * (p1.getX() - p0.getX()) - + alpha_i/delta_i * (p2.getX()-p1.getX()); - double y = (1-alpha_i)/delta_ib * (p1.getY() - p0.getY()) - + alpha_i/delta_i * (p2.getY()-p1.getY()); - - return new Point2D.Double(x,y); - } - - private static Point2D besselEndTangent(Point2D p0, Point2D p1, double delta_u, Point2D m){ - double x = 2*((p1.getX()-p0.getX())/delta_u) - m.getX(); - double y = 2*((p1.getY()-p0.getY())/delta_u) - m.getY(); - return new Point2D.Double(x,y); - } - - private static Point2D b3iBefore(Point2D b3i, double delta_ib, double delta_i, Point2D li){ - double x = b3i.getX() - (delta_ib/(3*(delta_ib+delta_i)))*li.getX(); - double y = b3i.getY() - (delta_ib/(3*(delta_ib+delta_i)))*li.getY(); - return new Point.Double(x,y); - } - - private static Point2D b3iAfter(Point2D b3i, double delta_ib,double delta_i,Point2D li){ - double x = b3i.getX() + (delta_i/(3*(delta_ib+delta_i)))*li.getX(); - double y = b3i.getY() + (delta_i/(3*(delta_ib+delta_i)))*li.getY(); - return new Point.Double(x,y); - } - - - - - //returns length of vector v - private static double norm(Point2D v){ - return Math.sqrt(v.getX()*v.getX()+v.getY()*v.getY()); - } - - //returns unity vector of vector v - private static Point2D normalize(Point2D v){ - double norm = norm(v); - if(norm==0) return new Point2D.Double(v.getX(), v.getY()); - return new Point2D.Double(v.getX()/norm , v.getY()/norm); - } - - //scale vector to size of length - private static Point2D scale(Point2D v, double length){ - Point2D tmp = normalize(v); - return new Point2D.Double(tmp.getX()*length, tmp.getY()*length); - } - - - - private GeneralPath subdivide2D (Point2D b0, Point2D b1, Point2D b2, Point2D b3) { - //set 2nd intermediate point to endpoint - //we could actually use another "better" point if we like to have a smoother curve - - double cutDistance = getTargetAnchorShape().getCutDistance(); - double minDistance = cutDistance - ENDPOINT_DEVIATION; - /** - * if the cutDistance is valid the last segment of the curve - * gets reduced by subdivision until the distance of the endpoint(epDistance) - * satisfys the condition (cutDistance > epDistance > (cutDistance - ENDPOINT-DEVIATION) - */ - if(cutDistance > minDistance && minDistance > 0 ) { - GeneralPath path = new GeneralPath(); - - path.moveTo(b0.getX(), b0.getY()); - - CubicCurve2D.Double curve = new CubicCurve2D.Double( - b0.getX(), b0.getY(), - b1.getX(), b1.getY(), - b2.getX(), b2.getY(), - b3.getX(), b3.getY()); - - - - CubicCurve2D right=new CubicCurve2D.Double(); - CubicCurve2D left=new CubicCurve2D.Double(); - curve.subdivide(left, right); - double distance = b3.distance(left.getP2()); - //if the distance is bigger as the cutDistance the left segment is added - //and the right segment is divided again - while(distance>cutDistance){ - path.append(left, true); - right.subdivide(left, right); - distance = b3.distance(left.getP2()); - //if the devision removed to much the left segment is divided - while(distance < minDistance) { - //changes the distance to ~ (distance+distance/2) - left.subdivide(left, right); - distance = b3.distance(left.getP2()); - } - } - //append the last segment with (minDistance < distance < cutDistance) - path.append(left, true); - return path; - } - return null; - } - - - /** - * Returns whether a specified local point pL is a part of the connection - * widget. - * First it make a rough bounds check - * for Line Segments => use Super call (ConnectionWidget.isHitAt(pL)). - * for self-edges => its sufficent to return getBounds.contains(pL). - * for Splines => Interate over all Partitial segments of the curve and make - * a minmax check with the bezier points. If pL is inside the minmax - * rectangle of one segment the curve is constructed and subdivided until - * the distance d between center point pC (of the bounding rectangle) - * and pL is below HIT_DISTANCE_SQUARE, in this case it returns true. - * If no no minmax check was successful or the subdivision lead to an - * rectangle witch doesn`t contain pL return false. - * @param localLocation the local location - * @return true, if the location is a part of the connection widget - */ - @Override - public boolean isHitAt(Point localLocation) { - if(!isVisible() || !getBounds ().contains (localLocation)) - return false; - - List controlPoints = getControlPoints (); - if(controlPoints.size() <=2){ - if(isReflexive()) return true; - return super.isHitAt(localLocation); - } - - if(bezierPoints != null) { - for (int i = 0; i < bezierPoints.length-1; i+=3) { - Point2D b0 = bezierPoints[i]; - Point2D b1 = bezierPoints[i+1]; - Point2D b2 = bezierPoints[i+2]; - Point2D b3 = bezierPoints[i+3]; - - CubicCurve2D left = new CubicCurve2D.Double( - b0.getX(), b0.getY(), - b1.getX(), b1.getY(), - b2.getX(), b2.getY(), - b3.getX(), b3.getY()); - - - Rectangle2D bounds = left.getBounds2D(); - while(bounds.contains(localLocation)) { - //calculate the center and use HIT_DISTANCE_SQUARE for a range check - Point2D test = new Point2D.Double(bounds.getCenterX(),bounds.getCenterY()); - if(test.distance(localLocation) < HIT_DISTANCE_SQUARE){ - return true; - } - - - CubicCurve2D right = new CubicCurve2D.Double(); - left.subdivide(left, right); - Rectangle2D lb2d = left.getBounds2D(); - Rectangle2D rb2d = right.getBounds2D(); - if( lb2d.contains(localLocation)){ - bounds = lb2d; - } else if (rb2d.contains(localLocation)) { - left = right; - bounds = rb2d; - } else { - return false; - } - - }//end while - }//end for - } - return false; - } - - -} - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/WidgetCollisionCollector.java --- a/visualizer/ControlFlowEditor/src/at/ssw/visualizer/cfg/visual/WidgetCollisionCollector.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -package at.ssw.visualizer.cfg.visual; - -import java.util.List; -import org.netbeans.api.visual.widget.Widget; - - -public interface WidgetCollisionCollector { - - //returns a list of widgets which should be handled as obstacles - void collectCollisions(List collisions); - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/build.xml --- a/visualizer/Data/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project com.sun.hotspot.igv.data. - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/manifest.mf --- a/visualizer/Data/manifest.mf Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.sun.hotspot.igv.data -OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/data/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/nbproject/build-impl.xml --- a/visualizer/Data/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/nbproject/genfiles.properties --- a/visualizer/Data/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -build.xml.data.CRC32=a403efd8 -build.xml.script.CRC32=b87f73ba -build.xml.stylesheet.CRC32=79c3b980 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=a403efd8 -nbproject/build-impl.xml.script.CRC32=cc649146 -nbproject/build-impl.xml.stylesheet.CRC32=deb65f65 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/nbproject/platform.properties --- a/visualizer/Data/nbproject/platform.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -# Deprecated since 5.0u1; for compatibility with 5.0: -disabled.clusters=\ - apisupport1,\ - harness,\ - ide8,\ - java1,\ - nb6.0,\ - profiler2 -disabled.modules=\ - org.netbeans.core.execution,\ - org.netbeans.core.multiview,\ - org.netbeans.core.output2,\ - org.netbeans.modules.applemenu,\ - org.netbeans.modules.autoupdate.services,\ - org.netbeans.modules.autoupdate.ui,\ - org.netbeans.modules.core.kit,\ - org.netbeans.modules.favorites,\ - org.netbeans.modules.javahelp,\ - org.netbeans.modules.masterfs,\ - org.netbeans.modules.options.keymap,\ - org.netbeans.modules.sendopts,\ - org.netbeans.modules.templates,\ - org.openide.compat,\ - org.openide.execution,\ - org.openide.util.enumerations -enabled.clusters=\ - platform7 -nbjdk.active=JDK_1.6 -nbplatform.active=default diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/nbproject/project.properties --- a/visualizer/Data/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -javac.source=1.7 -javac.compilerargs=-Xlint -Xlint:-serial -src.dir=src -build.test.classes.dir=${build.dir}/test/classes -build.test.results.dir=${build.dir}/test/results -test.src.dir=test -build.test.classes.dir=${build.dir}/test/classes -build.test.results.dir=${build.dir}/test/results diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/nbproject/project.xml --- a/visualizer/Data/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - com.sun.hotspot.igv.data - - - - - unit - - org.netbeans.libs.junit4 - - - - org.openide.util - - - - - - at.ssw.visualizer.model.bc - at.ssw.visualizer.model.cfg - at.ssw.visualizer.model.interval - at.ssw.visualizer.model.nc - com.sun.hotspot.igv.data - com.sun.hotspot.igv.data.serialization - com.sun.hotspot.igv.data.services - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/nbproject/suite.properties --- a/visualizer/Data/nbproject/suite.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -suite.dir=${basedir}/.. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/model/bc/Bytecodes.java --- a/visualizer/Data/src/at/ssw/visualizer/model/bc/Bytecodes.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -package at.ssw.visualizer.model.bc; - -import at.ssw.visualizer.model.cfg.ControlFlowGraph; - -/** - * This class holds the bytecode of a method and provides severel methods - * accessing the details. - * - * @author Alexander Reder - * @author Christian Wimmer - */ -public interface Bytecodes { - /** - * Back-link to the control flow graph where the bytecodes were loaded from. - */ - public ControlFlowGraph getControlFlowGraph(); - - /** - * Called before the first call of getBytecodes() or getEpilogue(). Can be called multiple times. - */ - public void parseBytecodes(); - - /** - * The bytecodes of the method in the given bytecode range. - * - * @param fromBCI starting BCI (including this bci) - * @param toBCI ending BCI (not including this bci) - * @return string representation of the bytecodes - */ - public String getBytecodes(int fromBCI, int toBCI); - - public String getEpilogue(); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/model/cfg/BasicBlock.java --- a/visualizer/Data/src/at/ssw/visualizer/model/cfg/BasicBlock.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -package at.ssw.visualizer.model.cfg; - -import java.util.List; - -/** - * - * @author Christian Wimmer - */ -public interface BasicBlock { - public String getName(); - - public int getFromBci(); - - public int getToBci(); - - public List getPredecessors(); - - public List getSuccessors(); - - public List getXhandlers(); - - public List getFlags(); - - public BasicBlock getDominator(); - - public int getLoopIndex(); - - public int getLoopDepth(); - - public boolean hasState(); - - public List getStates(); - - public boolean hasHir(); - - public List getHirInstructions(); - - public boolean hasLir(); - - public List getLirOperations(); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/model/cfg/ControlFlowGraph.java --- a/visualizer/Data/src/at/ssw/visualizer/model/cfg/ControlFlowGraph.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -package at.ssw.visualizer.model.cfg; - -import at.ssw.visualizer.model.bc.Bytecodes; -import at.ssw.visualizer.model.nc.NativeMethod; -import com.sun.hotspot.igv.data.FolderElement; -import java.util.List; - -/** - * - * @author Christian Wimmer - */ -public interface ControlFlowGraph extends FolderElement { - public List getBasicBlocks(); - - public BasicBlock getBasicBlockByName(String name); - - public Bytecodes getBytecodes(); - - public NativeMethod getNativeMethod(); - - public boolean hasState(); - - public boolean hasHir(); - - public boolean hasLir(); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/model/cfg/IRInstruction.java --- a/visualizer/Data/src/at/ssw/visualizer/model/cfg/IRInstruction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -package at.ssw.visualizer.model.cfg; - -import java.util.Collection; - -/** - * - * @author Christian Wimmer - */ -public interface IRInstruction { - public static String HIR_NAME = "tid"; - public static String HIR_TEXT = "instruction"; - public static String HIR_OPERAND = "result"; - - public static String LIR_NUMBER = "nr"; - public static String LIR_TEXT = "instruction"; - - public Collection getNames(); - public String getValue(String name); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/model/cfg/State.java --- a/visualizer/Data/src/at/ssw/visualizer/model/cfg/State.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -package at.ssw.visualizer.model.cfg; - -import java.util.List; - -/** - * - * @author Christian Wimmer - */ -public interface State { - public String getKind(); - - public int getSize(); - - public String getMethod(); - - public List getEntries(); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/model/cfg/StateEntry.java --- a/visualizer/Data/src/at/ssw/visualizer/model/cfg/StateEntry.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -package at.ssw.visualizer.model.cfg; - -import java.util.List; - -/** - * - * @author Christian Wimmer - */ -public interface StateEntry { - public int getIndex(); - - public String getName(); - - public boolean hasPhiOperands(); - - public List getPhiOperands(); - - public String getOperand(); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/model/interval/ChildInterval.java --- a/visualizer/Data/src/at/ssw/visualizer/model/interval/ChildInterval.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -package at.ssw.visualizer.model.interval; - -import java.util.List; - -/** - * - * @author Christian Wimmer - */ -public interface ChildInterval { - public Interval getParent(); - - public String getRegNum(); - - public String getType(); - - public String getOperand(); - - public String getSpillState(); - - public ChildInterval getRegisterHint(); - - public List getRanges(); - - public List getUsePositions(); - - public int getFrom(); - - public int getTo(); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/model/interval/Interval.java --- a/visualizer/Data/src/at/ssw/visualizer/model/interval/Interval.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -package at.ssw.visualizer.model.interval; - -import java.util.List; - -/** - * - * @author Christian Wimmer - */ -public interface Interval { - public IntervalList getParent(); - - public List getChildren(); - - public String getRegNum(); - - public int getFrom(); - - public int getTo(); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/model/interval/IntervalList.java --- a/visualizer/Data/src/at/ssw/visualizer/model/interval/IntervalList.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -package at.ssw.visualizer.model.interval; - -import at.ssw.visualizer.model.cfg.ControlFlowGraph; -import java.util.List; - -/** - * - * @author Christian Wimmer - */ -public interface IntervalList { - public List getIntervals(); - - public ControlFlowGraph getControlFlowGraph(); - - public int getNumLIROperations(); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/model/interval/Range.java --- a/visualizer/Data/src/at/ssw/visualizer/model/interval/Range.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -package at.ssw.visualizer.model.interval; - -/** - * - * @author Christian Wimmer - */ -public interface Range { - public int getFrom(); - - public int getTo(); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/model/interval/UsePosition.java --- a/visualizer/Data/src/at/ssw/visualizer/model/interval/UsePosition.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -package at.ssw.visualizer.model.interval; - -/** - * - * @author Christian Wimmer - */ -public interface UsePosition { - public char getKind(); - - public int getPosition(); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/model/nc/NativeMethod.java --- a/visualizer/Data/src/at/ssw/visualizer/model/nc/NativeMethod.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -package at.ssw.visualizer.model.nc; - -import at.ssw.visualizer.model.cfg.ControlFlowGraph; - -/** - * - * @author Alexander Reder - */ -public interface NativeMethod { - - public ControlFlowGraph getControlFlowGraph(); - - public String getMethodText(); - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/modelimpl/bc/BytecodesImpl.java --- a/visualizer/Data/src/at/ssw/visualizer/modelimpl/bc/BytecodesImpl.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,166 +0,0 @@ -package at.ssw.visualizer.modelimpl.bc; - -import at.ssw.visualizer.model.bc.Bytecodes; -import at.ssw.visualizer.model.cfg.BasicBlock; -import at.ssw.visualizer.model.cfg.ControlFlowGraph; -import at.ssw.visualizer.modelimpl.cfg.BasicBlockImpl; -import java.util.Arrays; - -/** - * This class holds the bytecode of a method and provides severel methods - * accessing the details. - * - * @author Christian Wimmer - */ -public class BytecodesImpl implements Bytecodes { - private ControlFlowGraph controlFlowGraph; - private String bytecodeString; - - private String[] bytecodes; - private String epilogue; - - - public BytecodesImpl(ControlFlowGraph controlFlowGraph, String bytecodeString) { - this.controlFlowGraph = controlFlowGraph; - this.bytecodeString = bytecodeString; - } - - public void parseBytecodes() { - String[] lines = bytecodeString.split("\n"); - - boolean inPrologue = true; - String[] result = new String[lines.length * 3]; - int lastBci = -1; - int lnr = 0; - for (; lnr < lines.length; lnr++) { - String line = lines[lnr]; - - line = line.trim(); - if (line.startsWith("[")) { - int end = line.indexOf(']'); - if (end != -1) { - line = line.substring(end + 1, line.length()); - } - } - - line = line.trim(); - int space1 = line.indexOf(' '); - if (space1 <= 0) { - if (inPrologue) { - continue; - } else { - break; - } - } - String bciStr = line.substring(0, space1); - if (bciStr.endsWith(":")) { - bciStr = bciStr.substring(0, bciStr.length() - 1); - } - - int bci; - try { - bci = Integer.parseInt(bciStr); - } catch (NumberFormatException ex) { - // Ignore invalid lines. - if (inPrologue) { - continue; - } else { - break; - } - } - - String opcode = line.substring(space1 + 1); - String params = ""; - int space2 = opcode.indexOf(' '); - if (space2 > 0) { - params = opcode.substring(space2 + 1).trim(); - opcode = opcode.substring(0, space2); - } - String tail = ""; - int space3 = params.indexOf('|'); - if (space3 >= 0) { - tail = params.substring(space3); - params = params.substring(0, space3); - } - -// if (!"ldc".equals(opcode) || !params.startsWith("\"")) { -// // Separate packages with "." instead of "/" -// params = params.replace('/', '.'); -// } - - String printLine = bciStr + ":" + " ".substring(Math.min(bciStr.length(), 3)) + - opcode + " ".substring(Math.min(opcode.length(), 13)) + - params + " ".substring(Math.min(params.length(), 8)) + - tail; - - - if (bci >= result.length) { - result = Arrays.copyOf(result, Math.max(bci + 1, result.length * 2)); - } - result[bci] = printLine; - inPrologue = false; - lastBci = Math.max(lastBci, bci); - } - - StringBuilder epilogueBuilder = new StringBuilder(); - for (; lnr < lines.length; lnr++) { - epilogueBuilder.append(lines[lnr]).append("\n"); - } - epilogue = epilogueBuilder.toString(); - bytecodes = Arrays.copyOf(result, lastBci + 1); - - - BasicBlockImpl[] blocks = new BasicBlockImpl[bytecodes.length]; - for (BasicBlock b : controlFlowGraph.getBasicBlocks()) { - if (b instanceof BasicBlockImpl) { - BasicBlockImpl block = (BasicBlockImpl) b; - if (block.getToBci() != -1) { - // Do not override existing values. - return; - } - if (block.getFromBci() >= 0 && block.getFromBci() < blocks.length) { - blocks[block.getFromBci()] = block; - } - } - } - - int curToBci = -1; - for (int i = blocks.length - 1; i >= 0; i--) { - if (bytecodes[i] != null && curToBci == -1) { - curToBci = i; - } - if (blocks[i] != null) { - blocks[i].setToBci(curToBci); - curToBci = -1; - } - } - } - - public ControlFlowGraph getControlFlowGraph() { - return controlFlowGraph; - } - - public String getBytecodes(int fromBCI, int toBCI) { - if (fromBCI < 0) { - return ""; - } - toBCI = Math.min(toBCI, bytecodes.length); - StringBuilder sb = new StringBuilder(); - for (int i = fromBCI; i < toBCI; i++) { - if (bytecodes[i] != null) { - sb.append(bytecodes[i]).append("\n"); - } - } - return sb.toString(); - } - - @Override - public String getEpilogue() { - return epilogue; - } - - @Override - public String toString() { - return "Bytecodes " + getControlFlowGraph().getName(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/BasicBlockImpl.java --- a/visualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/BasicBlockImpl.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -package at.ssw.visualizer.modelimpl.cfg; - -import at.ssw.visualizer.model.cfg.BasicBlock; -import at.ssw.visualizer.model.cfg.ControlFlowGraph; -import at.ssw.visualizer.model.cfg.IRInstruction; -import at.ssw.visualizer.model.cfg.State; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * - * @author Christian Wimmer - */ -public class BasicBlockImpl implements BasicBlock { - - private ControlFlowGraph parent; - private String name; - private int fromBci; - private int toBci; - private BasicBlock[] predecessors; - private BasicBlock[] successors; - private BasicBlock[] xhandlers; - private String[] flags; - private BasicBlock dominator; - private int loopIndex; - private int loopDepth; - private int firstLirId; - private int lastLirId; - private State[] states; - private IRInstruction[] hirInstructions; - private IRInstruction[] lirOperations; - - public void setValues(String name, int fromBci, int toBci, BasicBlock[] predecessors, BasicBlock[] successors, BasicBlock[] xhandlers, String[] flags, BasicBlock dominator, int loopIndex, int loopDepth, int firstLirId, int lastLirId, State[] states, IRInstruction[] hirInstructions, IRInstruction[] lirOperations) { - this.name = name; - this.fromBci = fromBci; - this.toBci = toBci; - - this.predecessors = predecessors; - this.successors = successors; - this.xhandlers = xhandlers; - - this.flags = flags; - this.dominator = dominator; - this.loopIndex = loopIndex; - this.loopDepth = loopDepth; - this.firstLirId = firstLirId; - this.lastLirId = lastLirId; - - this.states = states; - this.hirInstructions = hirInstructions; - this.lirOperations = lirOperations; - } - - public ControlFlowGraph getParent() { - return parent; - } - - protected void setParent(ControlFlowGraph parent) { - this.parent = parent; - } - - public String getName() { - return name; - } - - public int getFromBci() { - return fromBci; - } - - public int getToBci() { - return toBci; - } - - public void setToBci(int toBci) { - this.toBci = toBci; - } - - public List getPredecessors() { - return Collections.unmodifiableList(Arrays.asList(predecessors)); - } - - public List getSuccessors() { - return Collections.unmodifiableList(Arrays.asList(successors)); - } - - public List getXhandlers() { - return Collections.unmodifiableList(Arrays.asList(xhandlers)); - } - - public List getFlags() { - return Collections.unmodifiableList(Arrays.asList(flags)); - } - - public BasicBlock getDominator() { - return dominator; - } - - public int getLoopIndex() { - return loopIndex; - } - - public int getLoopDepth() { - return loopDepth; - } - - public int getFirstLirId() { - return firstLirId; - } - - public int getLastLirId() { - return lastLirId; - } - - public boolean hasState() { - return states != null; - } - - public List getStates() { - return Collections.unmodifiableList(Arrays.asList(states)); - } - - public boolean hasHir() { - return hirInstructions != null; - } - - public List getHirInstructions() { - return Collections.unmodifiableList(Arrays.asList(hirInstructions)); - } - - public boolean hasLir() { - return lirOperations != null; - } - - public List getLirOperations() { - return Collections.unmodifiableList(Arrays.asList(lirOperations)); - } - - @Override - public String toString() { - return name; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/IRInstructionImpl.java --- a/visualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/IRInstructionImpl.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -package at.ssw.visualizer.modelimpl.cfg; - -import at.ssw.visualizer.model.cfg.IRInstruction; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashMap; - -public class IRInstructionImpl implements IRInstruction { - private LinkedHashMap data; - - public IRInstructionImpl(LinkedHashMap data) { - this.data = data; - } - - public IRInstructionImpl(String pinned, int bci, int useCount, String name, String text, String operand) { - data = new LinkedHashMap(); - data.put("p", pinned); - data.put("bci", Integer.toString(bci)); - data.put("use", Integer.toString(useCount)); - data.put(HIR_NAME, name); - if (operand != null) { - data.put(HIR_OPERAND, operand); - } - data.put(HIR_TEXT, text); - } - - public IRInstructionImpl(int number, String text) { - data = new LinkedHashMap(); - data.put(LIR_NUMBER, Integer.toString(number)); - data.put(LIR_TEXT, text); - } - - public Collection getNames() { - return Collections.unmodifiableSet(data.keySet()); - } - - public String getValue(String name) { - return data.get(name); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/StateEntryImpl.java --- a/visualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/StateEntryImpl.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -package at.ssw.visualizer.modelimpl.cfg; - -import at.ssw.visualizer.model.cfg.StateEntry; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * - * @author Christian Wimmer - */ -public class StateEntryImpl implements StateEntry { - private int index; - private String name; - private String[] phiOperands; - private String operand; - - public StateEntryImpl(int index, String name, String[] phiOperands, String operand) { - this.index = index; - this.name = name; - this.phiOperands = phiOperands; - this.operand = operand; - } - - public int getIndex() { - return index; - } - - public String getName() { - return name; - } - - public boolean hasPhiOperands() { - return phiOperands != null; - } - - public List getPhiOperands() { - return Collections.unmodifiableList(Arrays.asList(phiOperands)); - } - - public String getOperand() { - return operand; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/StateImpl.java --- a/visualizer/Data/src/at/ssw/visualizer/modelimpl/cfg/StateImpl.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -package at.ssw.visualizer.modelimpl.cfg; - -import at.ssw.visualizer.model.cfg.State; -import at.ssw.visualizer.model.cfg.StateEntry; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * - * @author Christian Wimmer - */ -public class StateImpl implements State { - private String kind; - private int size; - private String method; - private StateEntry[] entries; - - public StateImpl(String kind, int size, String method, StateEntryImpl[] entries) { - this.kind = kind; - this.size = size; - this.method = method; - this.entries = entries; - } - - public String getKind() { - return kind; - } - - public int getSize() { - return size; - } - - public String getMethod() { - return method; - } - - public List getEntries() { - return Collections.unmodifiableList(Arrays.asList(entries)); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/modelimpl/interval/ChildIntervalImpl.java --- a/visualizer/Data/src/at/ssw/visualizer/modelimpl/interval/ChildIntervalImpl.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,118 +0,0 @@ -package at.ssw.visualizer.modelimpl.interval; - -import at.ssw.visualizer.model.interval.ChildInterval; -import at.ssw.visualizer.model.interval.Interval; -import at.ssw.visualizer.model.interval.Range; -import at.ssw.visualizer.model.interval.UsePosition; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * - * @author Christian Wimmer - */ -public class ChildIntervalImpl implements ChildInterval, Comparable { - private Interval parent; - private String regNum; - private String type; - private String operand; - private String spillState; - private ChildInterval registerHint; - private Range[] ranges; - private UsePosition[] usePositions; - - public void setValues(String regNum, String type, String operand, String spillState, ChildInterval registerHint, Range[] ranges, UsePosition[] usePositions) { - this.regNum = regNum; - this.type = type; - this.operand = operand; - this.spillState = spillState; - this.registerHint = registerHint; - this.ranges = ranges; - this.usePositions = usePositions; - } - - public Interval getParent() { - return parent; - } - - protected void setParent(IntervalImpl parent) { - this.parent = parent; - } - - public String getRegNum() { - return regNum; - } - - public String getType() { - return type; - } - - public String getOperand() { - return operand; - } - - public String getSpillState() { - return spillState; - } - - public ChildInterval getRegisterHint() { - return registerHint; - } - - public List getRanges() { - return Collections.unmodifiableList(Arrays.asList(ranges)); - } - - public List getUsePositions() { - return Collections.unmodifiableList(Arrays.asList(usePositions)); - } - - - public int getFrom() { - return ranges[0].getFrom(); - } - - public int getTo() { - return ranges[ranges.length - 1].getTo(); - } - - - public int compareTo(ChildIntervalImpl other) { - return getFrom() - other.getFrom(); - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - result.append(regNum); - result.append(": "); - result.append(getType()); - result.append(", "); - result.append(getOperand()); - result.append(", "); - if (registerHint != null) { - result.append(registerHint.getRegNum()); - } else { - result.append("null"); - } - - result.append(" "); - for (int i = 0; i < ranges.length; i++) { - if (i > 0) { - result.append(", "); - } - result.append(ranges[i]); - } - - result.append(" "); - for (int i = 0; i < usePositions.length; i++) { - if (i > 0) { - result.append(", "); - } - result.append(usePositions[i]); - } - - return result.toString(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/modelimpl/interval/IntervalImpl.java --- a/visualizer/Data/src/at/ssw/visualizer/modelimpl/interval/IntervalImpl.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -package at.ssw.visualizer.modelimpl.interval; - -import at.ssw.visualizer.model.interval.ChildInterval; -import at.ssw.visualizer.model.interval.Interval; -import at.ssw.visualizer.model.interval.IntervalList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * - * @author Christian Wimmer - */ -public class IntervalImpl implements Interval { - private IntervalList parent; - private ChildInterval[] children; - - public IntervalImpl(ChildIntervalImpl[] children) { - this.children = children; - for (ChildIntervalImpl child : children) { - child.setParent(this); - } - } - - public IntervalList getParent() { - return parent; - } - - protected void setParent(IntervalListImpl parent) { - this.parent = parent; - } - - public List getChildren() { - return Collections.unmodifiableList(Arrays.asList(children)); - } - - public String getRegNum() { - return children[0].getRegNum(); - } - - public int getFrom() { - return children[0].getFrom(); - } - - public int getTo() { - return children[children.length - 1].getTo(); - } - - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - for (int i = 0; i < children.length; i++) { - if (i > 0) { - result.append("\n "); - } - result.append(children[i]); - } - return result.toString(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/modelimpl/interval/IntervalListImpl.java --- a/visualizer/Data/src/at/ssw/visualizer/modelimpl/interval/IntervalListImpl.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -package at.ssw.visualizer.modelimpl.interval; - -import at.ssw.visualizer.model.cfg.BasicBlock; -import at.ssw.visualizer.model.cfg.ControlFlowGraph; -import at.ssw.visualizer.model.interval.Interval; -import at.ssw.visualizer.model.interval.IntervalList; -import com.sun.hotspot.igv.data.AbstractFolderElement; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -/** - * - * @author Christian Wimmer - */ -public class IntervalListImpl extends AbstractFolderElement implements IntervalList { - private Interval[] intervals; - private ControlFlowGraph controlFlowGraph; - private int numLIROperations; - - public IntervalListImpl(String shortName, String name, IntervalImpl[] intervals, ControlFlowGraph controlFlowGraph) { - super(shortName, name); - this.intervals = intervals; - this.controlFlowGraph = controlFlowGraph; - - for (IntervalImpl interval : intervals) { - interval.setParent(this); - numLIROperations = Math.max(numLIROperations, interval.getTo()); - } -// for (BasicBlock basicBlock : controlFlowGraph.getBasicBlocks()) { -// numLIROperations = Math.max(numLIROperations, basicBlock.getLastLirId() + 2); -// } - // TODO(tw): Add number of LIR operations to output. - } - - - public List getIntervals() { - return Collections.unmodifiableList(Arrays.asList(intervals)); - } - - public ControlFlowGraph getControlFlowGraph() { - return controlFlowGraph; - } - - public int getNumLIROperations() { - return numLIROperations; - } - - - @Override - public String toString() { - return " Intervals \"" + getName() + "\": " + intervals.length + " intervals\n"; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/modelimpl/interval/RangeImpl.java --- a/visualizer/Data/src/at/ssw/visualizer/modelimpl/interval/RangeImpl.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -package at.ssw.visualizer.modelimpl.interval; - -import at.ssw.visualizer.model.interval.Range; - -/** - * - * @author Christian Wimmer - */ -public class RangeImpl implements Range, Comparable { - private int from; - private int to; - - public RangeImpl(int from, int to) { - this.from = from; - this.to = to; - } - - - public int getFrom() { - return from; - } - - public int getTo() { - return to; - } - - - public int compareTo(RangeImpl other) { - return getFrom() - other.getFrom(); - } - - @Override - public String toString() { - return "[" + from + ", " + to + "]"; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/modelimpl/interval/UsePositionImpl.java --- a/visualizer/Data/src/at/ssw/visualizer/modelimpl/interval/UsePositionImpl.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -package at.ssw.visualizer.modelimpl.interval; - -import at.ssw.visualizer.model.interval.UsePosition; - -/** - * - * @author Christian Wimmer - */ -public class UsePositionImpl implements UsePosition, Comparable { - private int position; - private char kind; - - public UsePositionImpl(int position, char kind) { - this.position = position; - this.kind = kind; - } - - - public char getKind() { - return kind; - } - - public int getPosition() { - return position; - } - - - public int compareTo(UsePositionImpl other) { - return getPosition() - other.getPosition(); - } - - @Override - public String toString() { - return position + "(" + kind + ")"; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/at/ssw/visualizer/modelimpl/nc/NativeMethodImpl.java --- a/visualizer/Data/src/at/ssw/visualizer/modelimpl/nc/NativeMethodImpl.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -package at.ssw.visualizer.modelimpl.nc; - -import at.ssw.visualizer.model.cfg.ControlFlowGraph; -import at.ssw.visualizer.model.nc.NativeMethod; - -/** - * - * @author Alexander Reder - */ -public class NativeMethodImpl implements NativeMethod { - - private ControlFlowGraph controlFlowGraph; - private String methodText; - - public NativeMethodImpl(ControlFlowGraph controlFlowGraph, String methodText) { - this.controlFlowGraph = controlFlowGraph; - this.methodText = methodText; - } - - public ControlFlowGraph getControlFlowGraph() { - return controlFlowGraph; - } - - public String getMethodText() { - return methodText; - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/AbstractFolderElement.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/AbstractFolderElement.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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 com.sun.hotspot.igv.data; - -public class AbstractFolderElement implements FolderElement { - - private String name; - private String shortName; - private Folder parent; - - public AbstractFolderElement(String name, String shortName) { - this.name = name; - this.shortName = shortName; - } - - public String getShortName() { - return shortName; - } - - @Override - public String getName() { - return name; - } - - @Override - public Folder getParent() { - return parent; - } - - @Override - public void setParent(Folder parent) { - this.parent = parent; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/Bundle.properties --- a/visualizer/Data/src/com/sun/hotspot/igv/data/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -OpenIDE-Module-Name=Data diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/ChangedEvent.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/ChangedEvent.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data; - -public class ChangedEvent extends Event> { - - private T object; - - public ChangedEvent(T object) { - this.object = object; - } - - @Override - protected void fire(ChangedListener l) { - l.changed(object); - } - - public void changeObject(T newObject) { - if (object != newObject) { - this.object = newObject; - fire(); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/ChangedEventProvider.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/ChangedEventProvider.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/* - * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 com.sun.hotspot.igv.data; - -/** - * Provides a changed event object. - * @author Thomas Wuerthinger - * @param Class for which the changed event fires. - */ -public interface ChangedEventProvider { - - /** - * Returns the changed event object. Should always return the same instance. - */ - ChangedEvent getChangedEvent(); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/ChangedListener.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/ChangedListener.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data; - -/** - * Listens to changed events. - * @author Thomas Wuerthinger - * @param Class for which the changed event fires. - */ -public interface ChangedListener { - - /** - * This method is called everytime a changed event is fired. - * @param source Object that has changed. - */ - void changed(T source); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/ControllableChangedListener.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/ControllableChangedListener.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.sun.hotspot.igv.data; - -/** - * - * @author Thomas Wuerthinger - */ -public abstract class ControllableChangedListener implements ChangedListener{ - - private boolean enabled; - - - public ControllableChangedListener() { - enabled = true; - } - - public boolean isEnabled() { - return enabled; - } - - public void setEnabled(boolean b) { - enabled = b; - } - - @Override - public void changed(T source) { - if(enabled) { - filteredChanged(source); - } - } - - public abstract void filteredChanged(T source); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/Event.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/Event.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data; - -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public abstract class Event { - - private List listener; - private boolean fireEvents; - private boolean eventWasFired; - - public Event() { - listener = new ArrayList<>(); - fireEvents = true; - } - - public void addListener(L l) { - listener.add(l); - } - - public void addListenerAndFire(L l) { - addListener(l); - fire(l); - } - - /** - * Remove listener - * @param l - */ - public void removeListener(final L l) { - listener.remove(l); - } - - public void fire() { - if(fireEvents) { - List tmpList = new ArrayList<>(listener); - for (L l : tmpList) { - fire(l); - } - } else { - eventWasFired = true; - } - } - - public void beginAtomic() { - assert fireEvents : "endAtomic has to be called before another beginAtomic may be called"; - this.fireEvents = false; - this.eventWasFired = false; - } - - public void endAtomic() { - assert !fireEvents : "beginAtomic has to be called first"; - this.fireEvents = true; - if(eventWasFired) { - fire(); - } - } - - protected abstract void fire(L l); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/Folder.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/Folder.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data; - -import java.util.List; - -public interface Folder { - String getName(); - List getElements(); - void removeElement(FolderElement element); - void addElement(FolderElement group); - ChangedEvent getChangedEvent(); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/FolderElement.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/FolderElement.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data; - -public interface FolderElement { - - Folder getParent(); - String getName(); - void setParent(Folder parent); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/GraphDocument.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/GraphDocument.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data; - -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public class GraphDocument extends Properties.Entity implements ChangedEventProvider, Folder { - - private List elements; - private ChangedEvent changedEvent; - - public GraphDocument() { - elements = new ArrayList<>(); - changedEvent = new ChangedEvent<>(this); - } - - public void clear() { - elements.clear(); - getChangedEvent().fire(); - } - - @Override - public ChangedEvent getChangedEvent() { - return changedEvent; - } - - public void addGraphDocument(GraphDocument document) { - for (FolderElement e : document.elements) { - e.setParent(this); - this.addElement(e); - } - document.clear(); - getChangedEvent().fire(); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - - sb.append("GraphDocument: ").append(getProperties().toString()).append(" \n\n"); - for (FolderElement g : getElements()) { - sb.append(g.toString()); - sb.append("\n\n"); - } - - return sb.toString(); - } - - @Override - public List getElements() { - return elements; - } - - @Override - public void removeElement(FolderElement element) { - if (elements.remove(element)) { - getChangedEvent().fire(); - } - } - - @Override - public void addElement(FolderElement element) { - elements.add(element); - element.setParent(this); - getChangedEvent().fire(); - } - - @Override - public String getName() { - return "root"; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/Group.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/Group.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data; - -import java.util.*; - -/** - * - * @author Thomas Wuerthinger - */ -public class Group extends Properties.Entity implements ChangedEventProvider, Folder, FolderElement { - - private final List elements; - private final List graphs; - - private InputMethod method; - private transient ChangedEvent changedEvent; - private Folder parent; - - public Group(Folder parent) { - elements = new ArrayList<>(); - graphs = new ArrayList<>(); - changedEvent = new ChangedEvent<>(this); - this.parent = parent; - - // Ensure that name and type are never null - getProperties().setProperty("name", ""); - getProperties().setProperty("type", ""); - } - - public void fireChangedEvent() { - changedEvent.fire(); - } - - public void setMethod(InputMethod method) { - this.method = method; - } - - public InputMethod getMethod() { - return method; - } - - @Override - public ChangedEvent getChangedEvent() { - return changedEvent; - } - - @Override - public List getElements() { - return Collections.unmodifiableList(elements); - } - - public int getGraphsCount() { - return elements.size(); - } - - @Override - public void addElement(FolderElement element) { - elements.add(element); - if (element instanceof InputGraph) { - graphs.add((InputGraph) element); - } else { - - } - element.setParent(this); - changedEvent.fire(); - } - - public Set getAllNodes() { - Set result = new HashSet<>(); - for (FolderElement e : elements) { - if (e instanceof InputGraph) { - InputGraph g = (InputGraph) e; - result.addAll(g.getNodesAsSet()); - } - } - return result; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("Group ").append(getProperties()).append("\n"); - for (FolderElement g : elements) { - sb.append(g.toString()); - sb.append('\n'); - } - return sb.toString(); - } - - @Override - public String getName() { - return getProperties().get("name"); - } - - public String getType() { - return getProperties().get("type"); - - } - - InputGraph getPrev(InputGraph graph) { - InputGraph lastGraph = null; - for (FolderElement e : elements) { - if (e == graph) { - return lastGraph; - } - if (e instanceof InputGraph) { - lastGraph = (InputGraph) e; - } - } - return null; - } - - InputGraph getNext(InputGraph graph) { - boolean found = false; - for (FolderElement e : elements) { - if (e == graph) { - found = true; - } else if (found && e instanceof InputGraph) { - return (InputGraph) e; - } - } - return null; - } - - public InputGraph getLastGraph() { - InputGraph lastGraph = null; - for (FolderElement e : elements) { - if (e instanceof InputGraph) { - lastGraph = (InputGraph) e; - } - } - return lastGraph; - } - - @Override - public Folder getParent() { - return parent; - } - - @Override - public void removeElement(FolderElement element) { - if (elements.remove(element)) { - if (element instanceof InputGraph) { - graphs.remove((InputGraph) element); - } - changedEvent.fire(); - } - } - - public List getGraphs() { - return graphs; - } - - @Override - public void setParent(Folder parent) { - this.parent = parent; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/InputBlock.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,205 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data; - -import at.ssw.visualizer.model.cfg.BasicBlock; -import at.ssw.visualizer.model.cfg.ControlFlowGraph; -import at.ssw.visualizer.model.cfg.IRInstruction; -import at.ssw.visualizer.model.cfg.State; -import java.util.*; - -/** - * - * @author Thomas Wuerthinger - */ -public class InputBlock implements BasicBlock { - - private List nodes; - private String name; - private InputGraph graph; - private List successors; - private List predecessors; - - @Override - public int hashCode() { - return name.hashCode(); - } - - @Override - public boolean equals(Object o) { - - if (o == this) { - return true; - } - - if (o == null || (!(o instanceof InputBlock))) { - return false; - } - - final InputBlock b = (InputBlock)o; - final boolean result = b.nodes.equals(nodes) && b.name.equals(name) && b.successors.size() == successors.size(); - if (!result) { - return false; - } - - final HashSet s = new HashSet<>(); - for (InputBlock succ : successors) { - s.add(succ.name); - } - - for (InputBlock succ : b.successors) { - if (!s.contains(succ.name)) { - return false; - } - } - - return true; - } - - InputBlock(InputGraph graph, String name) { - this.graph = graph; - this.name = name; - nodes = new ArrayList<>(); - successors = new ArrayList<>(); - predecessors = new ArrayList<>(); - } - - public String getName() { - return name; - } - - public List getNodes() { - return Collections.unmodifiableList(nodes); - } - - public void addNode(int id) { - InputNode n = graph.getNode(id); - assert n != null; - graph.setBlock(n, this); - final InputNode node = graph.getNode(id); - assert node != null; - assert !nodes.contains(node) : "duplicate : " + node; - nodes.add(node); - } - - @Override - public List getSuccessors() { - return Collections.unmodifiableList(successors); - } - - @Override - public String toString() { - return "Block " + this.getName(); - } - - void addSuccessor(InputBlock b) { - if (!successors.contains(b)) { - successors.add(b); - b.predecessors.add(this); - } - } - - @Override - public int getFromBci() { - // TODO(tw): Implement. - return -1; - } - - @Override - public int getToBci() { - // TODO(tw): Implement. - return -1; - } - - @Override - public List getPredecessors() { - return Collections.unmodifiableList(predecessors); - } - - @Override - public List getXhandlers() { - // TODO(tw): Implement. - return Collections.emptyList(); - } - - @Override - public List getFlags() { - // TODO(tw): Implement. - return Collections.emptyList(); - } - - @Override - public BasicBlock getDominator() { - // TODO(tw): Implement. - return null; - } - - @Override - public int getLoopIndex() { - // TODO(tw): Implement. - return -1; - } - - @Override - public int getLoopDepth() { - // TODO(tw): Implement. - return -1; - } - - @Override - public boolean hasState() { - // TODO(tw): Implement. - return false; - } - - @Override - public List getStates() { - // TODO(tw): Implement. - return Collections.emptyList(); - } - - @Override - public boolean hasHir() { - // TODO(tw): Implement. - return false; - } - - @Override - public List getHirInstructions() { - // TODO(tw): Implement. - return Collections.emptyList(); - } - - @Override - public boolean hasLir() { - // TODO(tw): Implement. - return false; - } - - @Override - public List getLirOperations() { - // TODO(tw): Implement. - return Collections.emptyList(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/InputBlockEdge.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/InputBlockEdge.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data; - -/** - * - * @author Thomas Wuerthinger - */ -public class InputBlockEdge { - - public enum State { - SAME, - NEW, - DELETED - } - - private InputBlock from; - private InputBlock to; - private State state = State.SAME; - - public InputBlockEdge(InputBlock from, InputBlock to) { - assert from != null; - assert to != null; - this.from = from; - this.to = to; - } - - public InputBlock getFrom() { - return from; - } - - public InputBlock getTo() { - return to; - } - - public State getState() { - return state; - } - - public void setState(State state) { - this.state = state; - } - - @Override - public boolean equals(Object obj) { - if (obj != null && obj instanceof InputBlockEdge) { - InputBlockEdge e = (InputBlockEdge) obj; - return e.from.equals(from) && e.to.equals(to); - } - return false; - } - - @Override - public int hashCode() { - int hash = from.hashCode(); - hash = 59 * hash + to.hashCode(); - return hash; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/InputBytecode.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/InputBytecode.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data; - -/** - * - * @author Thomas Wuerthinger - */ -public class InputBytecode { - - private int bci; - private String name; - private String operands; - private String comment; - private InputMethod inlined; - - public InputBytecode(int bci, String name, String operands, String comment) { - this.bci = bci; - this.name = name; - this.operands = operands; - this.comment = comment; - } - - public InputMethod getInlined() { - return inlined; - } - - public void setInlined(InputMethod inlined) { - this.inlined = inlined; - } - - public int getBci() { - return bci; - } - - public String getName() { - return name; - } - - public String getOperands() { - return operands; - } - - public String getComment() { - return comment; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/InputEdge.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/InputEdge.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data; - -import java.util.Comparator; - -/** - * - * @author Thomas Wuerthinger - */ -public class InputEdge { - - public enum State { - - SAME, - NEW, - DELETED - } - - public static final Comparator OUTGOING_COMPARATOR = new Comparator(){ - - @Override - public int compare(InputEdge o1, InputEdge o2) { - if(o1.getFromIndex() == o2.getFromIndex()) { - return o1.getTo() - o2.getTo(); - } - return o1.getFromIndex() - o2.getFromIndex(); - } - }; - - - public static final Comparator INGOING_COMPARATOR = new Comparator(){ - - @Override - public int compare(InputEdge o1, InputEdge o2) { - if(o1.getToIndex() == o2.getToIndex()) { - return o1.getFrom() - o2.getFrom(); - } - return o1.getToIndex() - o2.getToIndex(); - } - }; - - private char toIndex; - private char fromIndex; - private int from; - private int to; - private State state; - private String label; - - public InputEdge(char toIndex, int from, int to) { - this((char) 0, toIndex, from, to, null); - } - - public InputEdge(char fromIndex, char toIndex, int from, int to) { - this(fromIndex, toIndex, from, to, null); - } - - public InputEdge(char fromIndex, char toIndex, int from, int to, String label) { - this.toIndex = toIndex; - this.fromIndex = fromIndex; - this.from = from; - this.to = to; - this.state = State.SAME; - this.label = label; - } - - public State getState() { - return state; - } - - public void setState(State x) { - this.state = x; - } - - public char getToIndex() { - return toIndex; - } - - public char getFromIndex() { - return fromIndex; - } - - public String getName() { - return "in" + toIndex; - } - - public int getFrom() { - return from; - } - - public int getTo() { - return to; - } - - public String getLabel() { - return label; - } - - @Override - public boolean equals(Object o) { - if (o == null || !(o instanceof InputEdge)) { - return false; - } - InputEdge conn2 = (InputEdge) o; - return conn2.fromIndex == fromIndex && conn2.toIndex == toIndex && conn2.from == from && conn2.to == to; - } - - @Override - public String toString() { - return "Edge from " + from + " to " + to + "(" + (int) fromIndex + ", " + (int) toIndex + ") "; - } - - @Override - public int hashCode() { - return (from << 20 | to << 8 | toIndex << 4 | fromIndex); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/InputGraph.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,340 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data; - -import at.ssw.visualizer.model.bc.Bytecodes; -import at.ssw.visualizer.model.cfg.BasicBlock; -import at.ssw.visualizer.model.cfg.ControlFlowGraph; -import at.ssw.visualizer.model.nc.NativeMethod; -import java.util.*; - -/** - * - * @author Thomas Wuerthinger - */ -public class InputGraph extends Properties.Entity implements FolderElement, ControlFlowGraph { - - private Map nodes; - private Set edges; - private Folder parent; - private Group parentGroup; - private Map blocks; - private Set blockEdges; - private Map nodeToBlock; - - public InputGraph(String name) { - setName(name); - nodes = new LinkedHashMap<>(); - edges = new LinkedHashSet<>(); - blocks = new LinkedHashMap<>(); - blockEdges = new LinkedHashSet<>(); - nodeToBlock = new LinkedHashMap<>(); - } - - @Override - public void setParent(Folder parent) { - this.parent = parent; - if (parent instanceof Group) { - assert this.parentGroup == null; - this.parentGroup = (Group) parent; - } - } - - public InputBlockEdge addBlockEdge(InputBlock left, InputBlock right) { - InputBlockEdge edge = new InputBlockEdge(left, right); - blockEdges.add(edge); - left.addSuccessor(right); - return edge; - } - - public List findRootNodes() { - List result = new ArrayList<>(); - Set nonRoot = new HashSet<>(); - for(InputEdge curEdges : getEdges()) { - nonRoot.add(curEdges.getTo()); - } - - for(InputNode node : getNodes()) { - if(!nonRoot.contains(node.getId())) { - result.add(node); - } - } - - return result; - } - - public Map> findAllOutgoingEdges() { - - Map> result = new HashMap<>(getNodes().size()); - for(InputNode n : this.getNodes()) { - result.put(n, new ArrayList()); - } - - for(InputEdge e : this.edges) { - int from = e.getFrom(); - InputNode fromNode = this.getNode(from); - List fromList = result.get(fromNode); - assert fromList != null; - fromList.add(e); - } - - for(InputNode n : this.getNodes()) { - List list = result.get(n); - Collections.sort(list, InputEdge.OUTGOING_COMPARATOR); - } - - return result; - } - - public Map> findAllIngoingEdges() { - - Map> result = new HashMap<>(getNodes().size()); - for(InputNode n : this.getNodes()) { - result.put(n, new ArrayList()); - } - - for(InputEdge e : this.edges) { - int to = e.getTo(); - InputNode toNode = this.getNode(to); - List toList = result.get(toNode); - assert toList != null; - toList.add(e); - } - - for(InputNode n : this.getNodes()) { - List list = result.get(n); - Collections.sort(list, InputEdge.INGOING_COMPARATOR); - } - - return result; - } - - public List findOutgoingEdges(InputNode n) { - List result = new ArrayList<>(); - - for(InputEdge e : this.edges) { - if(e.getFrom() == n.getId()) { - result.add(e); - } - } - - Collections.sort(result, InputEdge.OUTGOING_COMPARATOR); - - return result; - } - - public void clearBlocks() { - blocks.clear(); - nodeToBlock.clear(); - } - - public void setEdge(int fromIndex, int toIndex, int from, int to) { - assert fromIndex == ((char)fromIndex) : "Downcast must be safe"; - assert toIndex == ((char)toIndex) : "Downcast must be safe"; - - InputEdge edge = new InputEdge((char)fromIndex, (char)toIndex, from, to); - if(!this.getEdges().contains(edge)) { - this.addEdge(edge); - } - } - - public void ensureNodesInBlocks() { - InputBlock noBlock = null; - Set scheduledNodes = new HashSet<>(); - - for (InputBlock b : getBlocks()) { - for (InputNode n : b.getNodes()) { - assert !scheduledNodes.contains(n); - scheduledNodes.add(n); - } - } - - for (InputNode n : this.getNodes()) { - assert nodes.get(n.getId()) == n; - if (!scheduledNodes.contains(n)) { - if (noBlock == null) { - noBlock = this.addBlock("(no block)"); - } - noBlock.addNode(n.getId()); - } - assert this.getBlock(n) != null; - } - } - - public void setBlock(InputNode node, InputBlock block) { - nodeToBlock.put(node.getId(), block); - } - - public InputBlock getBlock(int nodeId) { - return nodeToBlock.get(nodeId); - } - - public InputBlock getBlock(InputNode node) { - assert nodes.containsKey(node.getId()); - assert nodes.get(node.getId()).equals(node); - return getBlock(node.getId()); - } - - public InputGraph getNext() { - return parentGroup.getNext(this); - } - - public InputGraph getPrev() { - return parentGroup.getPrev(this); - } - - private void setName(String name) { - this.getProperties().setProperty("name", name); - } - - @Override - public String getName() { - return getProperties().get("name"); - } - - public Collection getNodes() { - return Collections.unmodifiableCollection(nodes.values()); - } - - public Set getNodesAsSet() { - return Collections.unmodifiableSet(nodes.keySet()); - } - - public Collection getBlocks() { - return Collections.unmodifiableCollection(blocks.values()); - } - - public void addNode(InputNode node) { - nodes.put(node.getId(), node); - } - - public InputNode getNode(int id) { - return nodes.get(id); - } - - public InputNode removeNode(int index) { - return nodes.remove(index); - } - - public Collection getEdges() { - return Collections.unmodifiableSet(edges); - } - - public void removeEdge(InputEdge c) { - boolean removed = edges.remove(c); - assert removed; - } - - public void addEdge(InputEdge c) { - // Be tolerant with duplicated edges. - if (!edges.contains(c)) { - edges.add(c); - } - } - - public Group getGroup() { - return parentGroup; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("Graph ").append(getName()).append(" ").append(getProperties().toString()).append("\n"); - for (InputNode n : nodes.values()) { - sb.append(n.toString()); - sb.append("\n"); - } - - for (InputEdge c : edges) { - sb.append(c.toString()); - sb.append("\n"); - } - - for (InputBlock b : getBlocks()) { - sb.append(b.toString()); - sb.append("\n"); - } - - return sb.toString(); - } - - public InputBlock addBlock(String name) { - final InputBlock b = new InputBlock(this, name); - blocks.put(b.getName(), b); - return b; - } - - public InputBlock getBlock(String s) { - return blocks.get(s); - } - - public Collection getBlockEdges() { - return Collections.unmodifiableSet(blockEdges); - } - - @Override - public Folder getParent() { - return parent; - } - - @Override - public List getBasicBlocks() { - return new ArrayList(blocks.values()); - } - - @Override - public BasicBlock getBasicBlockByName(String name) { - return blocks.get(name); - } - - @Override - public Bytecodes getBytecodes() { - // TODO(tw): no bytecodes - return null; - } - - @Override - public NativeMethod getNativeMethod() { - // TODO(tw): No native method. - return null; - } - - @Override - public boolean hasState() { - // TODO(tw): implement - return false; - } - - @Override - public boolean hasHir() { - // TODO(tw): Implement - return false; - } - - @Override - public boolean hasLir() { - // TODO(tw): Implement - return false; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/InputMethod.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * - * @author Thomas Wuerthinger - */ -public class InputMethod extends Properties.Entity { - - private String name; - private int bci; - private String shortName; - private List inlined; - private InputMethod parentMethod; - private Group group; - private List bytecodes; - - @Override - public int hashCode() { - int result = name.hashCode(); - result = result * 31 + bci; - result = result * 31 + shortName.hashCode(); - result = result * 31 + inlined.hashCode(); - result = result * 31 + bytecodes.hashCode(); - return result; - } - - @Override - public boolean equals(Object o) { - if (o == null || (!(o instanceof InputMethod))) { - return false; - } - - final InputMethod im = (InputMethod)o; - return name.equals(im.name) && bci == im.bci && shortName.equals(im.shortName) && - inlined.equals(im.inlined) && bytecodes.equals(im.bytecodes); - } - - - - /** Creates a new instance of InputMethod */ - public InputMethod(Group parent, String name, String shortName, int bci) { - this.group = parent; - this.name = name; - this.bci = bci; - this.shortName = shortName; - inlined = new ArrayList<>(); - bytecodes = new ArrayList<>(); - } - - public List getBytecodes() { - return Collections.unmodifiableList(bytecodes); - } - - public List getInlined() { - return Collections.unmodifiableList(inlined); - } - - public void addInlined(InputMethod m) { - - // assert bci unique - for (InputMethod m2 : inlined) { - assert m2.getBci() != m.getBci(); - } - - inlined.add(m); - assert m.parentMethod == null; - m.parentMethod = this; - - for (InputBytecode bc : bytecodes) { - if (bc.getBci() == m.getBci()) { - bc.setInlined(m); - } - } - } - - public Group getGroup() { - return group; - } - - public String getShortName() { - return shortName; - } - - public void setBytecodes(String text) { - Pattern instruction = Pattern.compile("\\s*(\\d+)\\s*:?\\s*(\\w+)\\s*(.*)(?://(.*))?"); - String[] strings = text.split("\n"); - int oldBci = -1; - for (String s : strings) { - s = s.trim(); - if (s.length() != 0) { - final Matcher matcher = instruction.matcher(s); - if (matcher.matches()) { - String bciString = matcher.group(1); - String opcode = matcher.group(2); - String operands = matcher.group(3).trim(); - String comment = matcher.group(4); - if (comment != null) { - comment = comment.trim(); - } - - int bci = Integer.parseInt(bciString); - - // assert correct order of bytecodes - assert bci > oldBci; - - InputBytecode bc = new InputBytecode(bci, opcode, operands, comment); - bytecodes.add(bc); - - for (InputMethod m : inlined) { - if (m.getBci() == bci) { - bc.setInlined(m); - break; - } - } - } else { - System.out.println("no match: " + s); - } - } - } - } - - public String getName() { - return name; - } - - public int getBci() { - return bci; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/InputNode.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/InputNode.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data; - -import java.util.Comparator; - -/** - * - * @author Thomas Wuerthinger - */ -public class InputNode extends Properties.Entity { - - private int id; - - public static final Comparator COMPARATOR = new Comparator() { - @Override - public int compare(InputNode o1, InputNode o2) { - return o1.getId() - o2.getId(); - } - }; - - public static Comparator getPropertyComparator(final String propertyName) { - return new Comparator() { - - @Override - public int compare(InputNode o1, InputNode o2) { - - int i1 = 0; - try { - i1 = Integer.parseInt(o1.getProperties().get(propertyName)); - } catch(NumberFormatException e) { - } - - int i2 = 0; - try { - i2 = Integer.parseInt(o2.getProperties().get(propertyName)); - } catch(NumberFormatException e) { - } - - return i1 - i2; - } - }; - } - - public InputNode(InputNode n) { - super(n); - setId(n.id); - } - - public InputNode(int id) { - setId(id); - } - - public void setId(int id) { - this.id = id; - getProperties().setProperty("id", "" + id); - } - - public int getId() { - return id; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof InputNode)) { - return false; - } - InputNode n = (InputNode) o; - return n.id == id; - } - - @Override - public int hashCode() { - return id * 13; - } - - @Override - public String toString() { - return "Node " + id + " " + getProperties().toString(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/Pair.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/Pair.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data; - -/** - * - * @author Thomas Wuerthinger - */ -public class Pair { - - private L l; - private R r; - - public Pair() { - } - - public Pair(L l, R r) { - this.l = l; - this.r = r; - } - - public L getLeft() { - return l; - } - - public void setLeft(L l) { - this.l = l; - } - - public R getRight() { - return r; - } - - public void setRight(R r) { - this.r = r; - } - - @Override - public boolean equals(Object o) { - if (o == null || !(o instanceof Pair)) { - return false; - } - Pair obj = (Pair) o; - boolean b1 = (l == obj.l); - if (l != null) { - b1 = l.equals(obj.l); - } - - boolean b2 = (r == obj.r); - if (r != null) { - b2 = r.equals(obj.r); - } - - return b1 && b2; - } - - @Override - public int hashCode() { - return ((l == null) ? 0 : l.hashCode()) * 71 + ((r == null) ? 0 : r.hashCode()); - } - - @Override - public String toString() { - return "[" + l + "/" + r + "]"; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/Properties.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/Properties.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,391 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data; - -import java.io.Serializable; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; - -/** - * - * @author Thomas Wuerthinger - */ -public class Properties implements Serializable, Iterable { - - public static final long serialVersionUID = 1L; - private String[] map = new String[4]; - - public Properties() { - } - - @Override - public boolean equals(java.lang.Object o) { - if (!(o instanceof Properties)) { - return false; - } - - Properties p = (Properties) o; - - for (Property prop : this) { - String value = p.get(prop.getName()); - if (value == null || !value.equals(prop.getValue())) { - return false; - } - } - - for (Property prop : p) { - String value = this.get(prop.getName()); - if (value == null || !value.equals(prop.getValue())) { - return false; - } - } - - return true; - } - - @Override - public int hashCode() { - int hash = 5; - - if (map != null) { - for (int i = 0; i < this.map.length; i++) { - if (map[i] == null) { - i++; - } else { - hash = hash * 83 + map[i].hashCode(); - } - } - } - return hash; - } - - public Properties(String name, String value) { - this(); - this.setProperty(name, value); - } - - public Properties(String name, String value, String name1, String value1) { - this(name, value); - this.setProperty(name1, value1); - } - - public Properties(String name, String value, String name1, String value1, String name2, String value2) { - this(name, value, name1, value1); - this.setProperty(name2, value2); - } - - public Properties(Properties p) { - map = new String[p.map.length]; - System.arraycopy(p.map, 0, map, 0, p.map.length); - } - - public static class Entity implements Provider { - - private Properties properties; - - public Entity() { - properties = new Properties(); - } - - public Entity(Properties.Entity object) { - properties = new Properties(object.getProperties()); - } - - @Override - public Properties getProperties() { - return properties; - } - } - - public interface PropertyMatcher { - - String getName(); - - boolean match(String value); - } - - public static class InvertPropertyMatcher implements PropertyMatcher { - - private PropertyMatcher matcher; - - public InvertPropertyMatcher(PropertyMatcher matcher) { - this.matcher = matcher; - } - - @Override - public String getName() { - return matcher.getName(); - } - - @Override - public boolean match(String p) { - if (p == null) { - return false; - } - return !matcher.match(p); - } - } - - public static class StringPropertyMatcher implements PropertyMatcher { - - private String name; - private String value; - - public StringPropertyMatcher(String name, String value) { - if (name == null) { - throw new IllegalArgumentException("Property name must not be null!"); - } - if (value == null) { - throw new IllegalArgumentException("Property value must not be null!"); - } - this.name = name; - this.value = value; - } - - @Override - public String getName() { - return name; - } - - @Override - public boolean match(String p) { - if (p == null) { - throw new IllegalArgumentException("Property value must not be null!"); - } - return p.equals(value); - } - } - - public static class RegexpPropertyMatcher implements PropertyMatcher { - - private String name; - private Pattern valuePattern; - - public RegexpPropertyMatcher(String name, String value) { - this(name, value, 0); - } - - public RegexpPropertyMatcher(String name, String value, int flags) { - - if (name == null) { - throw new IllegalArgumentException("Property name must not be null!"); - } - - if (value == null) { - throw new IllegalArgumentException("Property value pattern must not be null!"); - } - - this.name = name; - - try { - valuePattern = Pattern.compile(value, flags); - } catch (PatternSyntaxException e) { - throw new IllegalArgumentException("Bad pattern: " + value); - } - } - - @Override - public String getName() { - return name; - } - - @Override - public boolean match(String p) { - if (p == null) { - throw new IllegalArgumentException("Property value must not be null!"); - } - Matcher m = valuePattern.matcher(p); - return m.matches(); - } - } - - public Property selectSingle(PropertyMatcher matcher) { - - final String name = matcher.getName(); - String value = null; - for (int i = 0; i < map.length; i += 2) { - if (map[i] != null && name.equals(map[i])) { - value = map[i + 1]; - break; - } - } - if (value != null && matcher.match(value)) { - return new Property(name, value); - } else { - return null; - } - } - - public interface Provider { - - public Properties getProperties(); - } - - @Override - public String toString() { - List pairs = new ArrayList<>(); - for (int i = 0; i < map.length; i += 2) { - if (map[i + 1] != null) { - pairs.add(new String[]{map[i], map[i + 1]}); - } - } - - Collections.sort(pairs, new Comparator() { - @Override - public int compare(String[] o1, String[] o2) { - assert o1.length == 2; - assert o2.length == 2; - return o1[0].compareTo(o2[0]); - } - }); - - StringBuilder sb = new StringBuilder(); - sb.append("["); - boolean first = true; - for (String[] p : pairs) { - if (first) { - first = false; - } else { - sb.append(", "); - } - sb.append(p[0] + "=" + p[1]); - } - return sb.append("]").toString(); - } - - public static class PropertySelector { - - private Collection objects; - - public PropertySelector(Collection objects) { - this.objects = objects; - } - - public T selectSingle(PropertyMatcher matcher) { - - for (T t : objects) { - Property p = t.getProperties().selectSingle(matcher); - if (p != null) { - return t; - } - } - - return null; - } - - public List selectMultiple(PropertyMatcher matcher) { - List result = new ArrayList<>(); - - for (T t : objects) { - Property p = t.getProperties().selectSingle(matcher); - if (p != null) { - result.add(t); - } - } - - return result; - } - } - - public String get(String key) { - for (int i = 0; i < map.length; i += 2) { - if (map[i] != null && map[i].equals(key)) { - return map[i + 1]; - } - } - return null; - } - - public void setProperty(String name, String value) { - - for (int i = 0; i < map.length; i += 2) { - if (map[i] != null && map[i].equals(name)) { - String p = map[i + 1]; - if (value == null) { - // remove this property - map[i] = null; - map[i + 1] = null; - } else { - map[i + 1] = value; - } - return; - } - } - if (value == null) { - return; - } - for (int i = 0; i < map.length; i += 2) { - if (map[i] == null) { - map[i] = name; - map[i + 1] = value; - return; - } - } - String[] newMap = new String[map.length + 4]; - System.arraycopy(map, 0, newMap, 0, map.length); - newMap[map.length] = name; - newMap[map.length + 1] = value; - map = newMap; - } - - public void add(Properties properties) { - for (Property p : properties) { - setProperty(p.getName(), p.getValue()); - } - } - - private class PropertiesIterator implements Iterator { - - int index; - - @Override - public boolean hasNext() { - while (index < map.length && map[index + 1] == null) { - index += 2; - } - return index < map.length; - } - - @Override - public Property next() { - if (index < map.length) { - index += 2; - return new Property(map[index - 2], map[index - 1]); - } - return null; - } - - @Override - public void remove() { - throw new UnsupportedOperationException("Not supported yet."); - } - } - - @Override - public Iterator iterator() { - return new PropertiesIterator(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/Property.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/Property.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data; - -import java.io.Serializable; - -/** - * - * @author Thomas Wuerthinger - */ -public class Property implements Serializable { - - public static final long serialVersionUID = 1L; - private String name; - private String value; - - Property(String name, String value) { - this.name = name; - this.value = value; - - if (value == null) { - throw new IllegalArgumentException("Property value must not be null!"); - } - - if (name == null) { - throw new IllegalArgumentException("Property name must not be null!"); - } - } - - public String getName() { - return name; - } - - public String getValue() { - return value; - } - - @Override - public String toString() { - return name + "=" + value; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof Property)) { - return false; - } - Property p2 = (Property) o; - return name.equals(p2.name) && value.equals(p2.value); - } - - @Override - public int hashCode() { - return name.hashCode() * 13 + value.hashCode(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/Source.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/Source.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data; - -import java.util.*; - -/** - * - * @author Thomas Wuerthinger - */ -public class Source { - - private List sourceNodes; - private Set set; - - public Source() { - sourceNodes = new ArrayList<>(1); - set = new LinkedHashSet<>(1); - } - - public List getSourceNodes() { - return Collections.unmodifiableList(sourceNodes); - } - - public Set getSourceNodesAsSet() { - return Collections.unmodifiableSet(set); - } - - public void addSourceNode(InputNode n) { - if (!set.contains(n.getId())) { - sourceNodes.add(n); - set.add(n.getId()); - } - } - - public interface Provider { - - public Source getSource(); - } - - public void addSourceNodes(Source s) { - for (InputNode n : s.getSourceNodes()) { - addSourceNode(n); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/serialization/Parser.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,542 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data.serialization; - -import com.sun.hotspot.igv.data.*; -import com.sun.hotspot.igv.data.serialization.XMLParser.ElementHandler; -import com.sun.hotspot.igv.data.serialization.XMLParser.HandoverElementHandler; -import com.sun.hotspot.igv.data.serialization.XMLParser.ParseMonitor; -import com.sun.hotspot.igv.data.serialization.XMLParser.TopElementHandler; -import com.sun.hotspot.igv.data.services.GroupCallback; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; -import javax.swing.SwingUtilities; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParserFactory; -import javax.xml.transform.Source; -import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.SchemaFactory; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; - -/** - * - * @author Thomas Wuerthinger - */ -public class Parser { - - public static final String INDENT = " "; - public static final String TOP_ELEMENT = "graphDocument"; - public static final String GROUP_ELEMENT = "group"; - public static final String GRAPH_ELEMENT = "graph"; - public static final String ROOT_ELEMENT = "graphDocument"; - public static final String PROPERTIES_ELEMENT = "properties"; - public static final String EDGES_ELEMENT = "edges"; - public static final String PROPERTY_ELEMENT = "p"; - public static final String EDGE_ELEMENT = "edge"; - public static final String NODE_ELEMENT = "node"; - public static final String NODES_ELEMENT = "nodes"; - public static final String REMOVE_EDGE_ELEMENT = "removeEdge"; - public static final String REMOVE_NODE_ELEMENT = "removeNode"; - public static final String METHOD_NAME_PROPERTY = "name"; - public static final String GROUP_NAME_PROPERTY = "name"; - public static final String METHOD_IS_PUBLIC_PROPERTY = "public"; - public static final String METHOD_IS_STATIC_PROPERTY = "static"; - public static final String TRUE_VALUE = "true"; - public static final String NODE_NAME_PROPERTY = "name"; - public static final String EDGE_NAME_PROPERTY = "name"; - public static final String NODE_ID_PROPERTY = "id"; - public static final String FROM_PROPERTY = "from"; - public static final String TO_PROPERTY = "to"; - public static final String PROPERTY_NAME_PROPERTY = "name"; - public static final String GRAPH_NAME_PROPERTY = "name"; - public static final String FROM_INDEX_PROPERTY = "fromIndex"; - public static final String TO_INDEX_PROPERTY = "toIndex"; - public static final String TO_INDEX_ALT_PROPERTY = "index"; - public static final String LABEL_PROPERTY = "label"; - public static final String METHOD_ELEMENT = "method"; - public static final String INLINE_ELEMENT = "inline"; - public static final String BYTECODES_ELEMENT = "bytecodes"; - public static final String METHOD_BCI_PROPERTY = "bci"; - public static final String METHOD_SHORT_NAME_PROPERTY = "shortName"; - public static final String CONTROL_FLOW_ELEMENT = "controlFlow"; - public static final String BLOCK_NAME_PROPERTY = "name"; - public static final String BLOCK_ELEMENT = "block"; - public static final String SUCCESSORS_ELEMENT = "successors"; - public static final String SUCCESSOR_ELEMENT = "successor"; - public static final String ASSEMBLY_ELEMENT = "assembly"; - public static final String DIFFERENCE_PROPERTY = "difference"; - private TopElementHandler xmlDocument = new TopElementHandler<>(); - private Map differenceEncoding = new HashMap<>(); - private Map lastParsedGraph = new HashMap<>(); - private GroupCallback groupCallback; - private HashMap idCache = new HashMap<>(); - private ArrayList> blockConnections = new ArrayList<>(); - private int maxId = 0; - private GraphDocument graphDocument; - - private int lookupID(String i) { - try { - return Integer.parseInt(i); - } catch (NumberFormatException nfe) { - // ignore - } - Integer id = idCache.get(i); - if (id == null) { - id = maxId++; - idCache.put(i, id); - } - return id.intValue(); - } - - // - private ElementHandler topHandler = new ElementHandler(TOP_ELEMENT) { - - @Override - protected GraphDocument start() throws SAXException { - graphDocument = new GraphDocument(); - return graphDocument; - } - }; - // - private ElementHandler groupHandler = new XMLParser.ElementHandler(GROUP_ELEMENT) { - - @Override - protected Group start() throws SAXException { - final Group group = new Group(this.getParentObject()); - - String differenceProperty = this.readAttribute(DIFFERENCE_PROPERTY); - Parser.this.differenceEncoding.put(group, (differenceProperty != null && (differenceProperty.equals("1") || differenceProperty.equals("true")))); - - ParseMonitor monitor = getMonitor(); - if (monitor != null) { - monitor.setState(group.getName()); - } - - final Folder parent = getParentObject(); - if (groupCallback == null || parent instanceof Group) { - SwingUtilities.invokeLater(new Runnable(){ - @Override - public void run() { - parent.addElement(group); - } - }); - } - - return group; - } - - @Override - protected void end(String text) throws SAXException { - } - }; - // - private ElementHandler methodHandler = new XMLParser.ElementHandler(METHOD_ELEMENT) { - - @Override - protected InputMethod start() throws SAXException { - - InputMethod method = parseMethod(this, getParentObject()); - getParentObject().setMethod(method); - return method; - } - }; - - private InputMethod parseMethod(XMLParser.ElementHandler handler, Group group) throws SAXException { - String s = handler.readRequiredAttribute(METHOD_BCI_PROPERTY); - int bci = 0; - try { - bci = Integer.parseInt(s); - } catch (NumberFormatException e) { - throw new SAXException(e); - } - InputMethod method = new InputMethod(group, handler.readRequiredAttribute(METHOD_NAME_PROPERTY), handler.readRequiredAttribute(METHOD_SHORT_NAME_PROPERTY), bci); - return method; - } - // - private HandoverElementHandler bytecodesHandler = new XMLParser.HandoverElementHandler(BYTECODES_ELEMENT, true) { - - @Override - protected void end(String text) throws SAXException { - getParentObject().setBytecodes(text); - } - }; - // - private HandoverElementHandler inlinedHandler = new XMLParser.HandoverElementHandler<>(INLINE_ELEMENT); - // - private ElementHandler inlinedMethodHandler = new XMLParser.ElementHandler(METHOD_ELEMENT) { - - @Override - protected InputMethod start() throws SAXException { - InputMethod method = parseMethod(this, getParentObject().getGroup()); - getParentObject().addInlined(method); - return method; - } - }; - // - private ElementHandler graphHandler = new XMLParser.ElementHandler(GRAPH_ELEMENT) { - - @Override - protected InputGraph start() throws SAXException { - String name = readAttribute(GRAPH_NAME_PROPERTY); - InputGraph curGraph = new InputGraph(name); - if (differenceEncoding.get(getParentObject())) { - InputGraph previous = lastParsedGraph.get(getParentObject()); - lastParsedGraph.put(getParentObject(), curGraph); - if (previous != null) { - for (InputNode n : previous.getNodes()) { - curGraph.addNode(n); - } - for (InputEdge e : previous.getEdges()) { - curGraph.addEdge(e); - } - } - } - return curGraph; - } - - @Override - protected void end(String text) throws SAXException { - // NOTE: Some graphs intentionally don't provide blocks. Instead - // they later generate the blocks from other information such - // as node properties (example: ServerCompilerScheduler). - // Thus, we shouldn't assign nodes that don't belong to any - // block to some artificial block below unless blocks are - // defined and nodes are assigned to them. - - final InputGraph graph = getObject(); - final Group parent = getParentObject(); - if (graph.getBlocks().size() > 0) { - boolean blocksContainNodes = false; - for (InputBlock b : graph.getBlocks()) { - if (b.getNodes().size() > 0) { - blocksContainNodes = true; - break; - } - } - - if (!blocksContainNodes) { - graph.clearBlocks(); - blockConnections.clear(); - } else { - // Blocks and their nodes defined: add other nodes to an - // artificial "no block" block - InputBlock noBlock = null; - for (InputNode n : graph.getNodes()) { - if (graph.getBlock(n) == null) { - if (noBlock == null) { - noBlock = graph.addBlock("(no block)"); - } - - noBlock.addNode(n.getId()); - } - - assert graph.getBlock(n) != null; - } - } - } - - // Resolve block successors - for (Pair p : blockConnections) { - final InputBlock left = graph.getBlock(p.getLeft()); - assert left != null; - final InputBlock right = graph.getBlock(p.getRight()); - assert right != null; - graph.addBlockEdge(left, right); - } - blockConnections.clear(); - - SwingUtilities.invokeLater(new Runnable(){ - - @Override - public void run() { - // Add to group - parent.addElement(graph); - } - }); - } - }; - // - private HandoverElementHandler nodesHandler = new HandoverElementHandler<>(NODES_ELEMENT); - // - private HandoverElementHandler controlFlowHandler = new HandoverElementHandler<>(CONTROL_FLOW_ELEMENT); - // - private ElementHandler blockHandler = new ElementHandler(BLOCK_ELEMENT) { - - @Override - protected InputBlock start() throws SAXException { - InputGraph graph = getParentObject(); - String name = readRequiredAttribute(BLOCK_NAME_PROPERTY); - InputBlock b = graph.addBlock(name); - for (InputNode n : b.getNodes()) { - assert graph.getBlock(n).equals(b); - } - return b; - } - }; - // - private HandoverElementHandler blockNodesHandler = new HandoverElementHandler<>(NODES_ELEMENT); - // - private ElementHandler blockNodeHandler = new ElementHandler(NODE_ELEMENT) { - - @Override - protected InputBlock start() throws SAXException { - String s = readRequiredAttribute(NODE_ID_PROPERTY); - - int id = 0; - try { - id = lookupID(s); - } catch (NumberFormatException e) { - throw new SAXException(e); - } - getParentObject().addNode(id); - return getParentObject(); - } - }; - // - private HandoverElementHandler successorsHandler = new HandoverElementHandler<>(SUCCESSORS_ELEMENT); - // - private ElementHandler successorHandler = new ElementHandler(SUCCESSOR_ELEMENT) { - - @Override - protected InputBlock start() throws SAXException { - String name = readRequiredAttribute(BLOCK_NAME_PROPERTY); - blockConnections.add(new Pair<>(getParentObject().getName(), name)); - return getParentObject(); - } - }; - // - private ElementHandler nodeHandler = new ElementHandler(NODE_ELEMENT) { - - @Override - protected InputNode start() throws SAXException { - String s = readRequiredAttribute(NODE_ID_PROPERTY); - int id = 0; - try { - id = lookupID(s); - } catch (NumberFormatException e) { - throw new SAXException(e); - } - InputNode node = new InputNode(id); - getParentObject().addNode(node); - return node; - } - }; - // - private ElementHandler removeNodeHandler = new ElementHandler(REMOVE_NODE_ELEMENT) { - - @Override - protected InputNode start() throws SAXException { - String s = readRequiredAttribute(NODE_ID_PROPERTY); - int id = 0; - try { - id = lookupID(s); - } catch (NumberFormatException e) { - throw new SAXException(e); - } - return getParentObject().removeNode(id); - } - }; - // - private HandoverElementHandler edgesHandler = new HandoverElementHandler<>(EDGES_ELEMENT); - - // Local class for edge elements - private class EdgeElementHandler extends ElementHandler { - - public EdgeElementHandler(String name) { - super(name); - } - - @Override - protected InputEdge start() throws SAXException { - int fromIndex = 0; - int toIndex = 0; - int from = -1; - int to = -1; - String label = null; - - try { - String fromIndexString = readAttribute(FROM_INDEX_PROPERTY); - if (fromIndexString != null) { - fromIndex = Integer.parseInt(fromIndexString); - } - - String toIndexString = readAttribute(TO_INDEX_PROPERTY); - if (toIndexString == null) { - toIndexString = readAttribute(TO_INDEX_ALT_PROPERTY); - } - if (toIndexString != null) { - toIndex = Integer.parseInt(toIndexString); - } - - label = readAttribute(LABEL_PROPERTY); - - from = lookupID(readRequiredAttribute(FROM_PROPERTY)); - to = lookupID(readRequiredAttribute(TO_PROPERTY)); - } catch (NumberFormatException e) { - throw new SAXException(e); - } - - InputEdge conn = new InputEdge((char) fromIndex, (char) toIndex, from, to, label); - return start(conn); - } - - protected InputEdge start(InputEdge conn) throws SAXException { - return conn; - } - } - // - private EdgeElementHandler edgeHandler = new EdgeElementHandler(EDGE_ELEMENT) { - - @Override - protected InputEdge start(InputEdge conn) throws SAXException { - getParentObject().addEdge(conn); - return conn; - } - }; - // - private EdgeElementHandler removeEdgeHandler = new EdgeElementHandler(REMOVE_EDGE_ELEMENT) { - - @Override - protected InputEdge start(InputEdge conn) throws SAXException { - getParentObject().removeEdge(conn); - return conn; - } - }; - // - private HandoverElementHandler propertiesHandler = new HandoverElementHandler<>(PROPERTIES_ELEMENT); - // - private HandoverElementHandler groupPropertiesHandler = new HandoverElementHandler(PROPERTIES_ELEMENT) { - - @Override - public void end(String text) throws SAXException { - if (groupCallback != null && getParentObject().getParent() instanceof GraphDocument) { - final Group group = getParentObject(); - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - groupCallback.started(group); - } - }); - } - } - }; - // - private ElementHandler propertyHandler = new XMLParser.ElementHandler(PROPERTY_ELEMENT, true) { - - @Override - public String start() throws SAXException { - return readRequiredAttribute(PROPERTY_NAME_PROPERTY); - } - - @Override - public void end(String text) { - getParentObject().getProperties().setProperty(getObject(), text.trim()); - } - }; - - public Parser() { - this(null); - } - - public Parser(GroupCallback groupCallback) { - - this.groupCallback = groupCallback; - - // Initialize dependencies - xmlDocument.addChild(topHandler); - topHandler.addChild(groupHandler); - - groupHandler.addChild(methodHandler); - groupHandler.addChild(graphHandler); - groupHandler.addChild(groupHandler); - - methodHandler.addChild(inlinedHandler); - methodHandler.addChild(bytecodesHandler); - - inlinedHandler.addChild(inlinedMethodHandler); - inlinedMethodHandler.addChild(bytecodesHandler); - inlinedMethodHandler.addChild(inlinedHandler); - - graphHandler.addChild(nodesHandler); - graphHandler.addChild(edgesHandler); - graphHandler.addChild(controlFlowHandler); - - controlFlowHandler.addChild(blockHandler); - - blockHandler.addChild(successorsHandler); - successorsHandler.addChild(successorHandler); - blockHandler.addChild(blockNodesHandler); - blockNodesHandler.addChild(blockNodeHandler); - - nodesHandler.addChild(nodeHandler); - nodesHandler.addChild(removeNodeHandler); - edgesHandler.addChild(edgeHandler); - edgesHandler.addChild(removeEdgeHandler); - - methodHandler.addChild(propertiesHandler); - inlinedMethodHandler.addChild(propertiesHandler); - topHandler.addChild(propertiesHandler); - groupHandler.addChild(groupPropertiesHandler); - graphHandler.addChild(propertiesHandler); - nodeHandler.addChild(propertiesHandler); - propertiesHandler.addChild(propertyHandler); - groupPropertiesHandler.addChild(propertyHandler); - } - - // Returns a new GraphDocument object deserialized from an XML input source. - public GraphDocument parse(InputSource source, XMLParser.ParseMonitor monitor) throws SAXException { - XMLReader reader = createReader(); - - reader.setContentHandler(new XMLParser(xmlDocument, monitor)); - try { - reader.parse(source); - } catch (IOException ex) { - throw new SAXException(ex); - } - - return graphDocument; - } - - private XMLReader createReader() throws SAXException { - try { - SAXParserFactory pfactory = SAXParserFactory.newInstance(); - pfactory.setValidating(false); - pfactory.setNamespaceAware(true); - - // Enable schema validation - SchemaFactory sfactory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema"); - InputStream stream = Parser.class.getResourceAsStream("graphdocument.xsd"); - pfactory.setSchema(sfactory.newSchema(new Source[]{new StreamSource(stream)})); - - return pfactory.newSAXParser().getXMLReader(); - } catch (ParserConfigurationException ex) { - throw new SAXException(ex); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/serialization/Printer.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/serialization/Printer.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,245 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data.serialization; - -import com.sun.hotspot.igv.data.*; -import java.io.IOException; -import java.io.InputStream; -import java.io.Writer; -import java.util.HashSet; -import java.util.Set; - -/** - * - * @author Thomas Wuerthinger - */ -public class Printer { - - private InputStream in; - - public Printer() { - this(null); - } - - public Printer(InputStream inputStream) { - this.in = inputStream; - } - - public void export(Writer writer, GraphDocument document) { - - XMLWriter xmlWriter = new XMLWriter(writer); - - try { - export(xmlWriter, document); - } catch (IOException ex) { - } - } - - private void export(XMLWriter xmlWriter, GraphDocument document) throws IOException { - xmlWriter.startTag(Parser.ROOT_ELEMENT); - xmlWriter.writeProperties(document.getProperties()); - for (FolderElement e : document.getElements()) { - if (e instanceof Group) { - export(xmlWriter, (Group) e); - } else if (e instanceof InputGraph) { - export(xmlWriter, (InputGraph)e, null, false); - } - } - - xmlWriter.endTag(); - xmlWriter.flush(); - } - - private void export(XMLWriter writer, Group g) throws IOException { - Properties attributes = new Properties(); - attributes.setProperty("difference", Boolean.toString(true)); - writer.startTag(Parser.GROUP_ELEMENT, attributes); - writer.writeProperties(g.getProperties()); - - boolean shouldExport = true; - if (in != null) { - char c = (char) in.read(); - if (c != 'y') { - shouldExport = false; - } - } - - if (shouldExport) { - if (g.getMethod() != null) { - export(writer, g.getMethod()); - } - - InputGraph previous = null; - for (FolderElement e : g.getElements()) { - if (e instanceof InputGraph) { - InputGraph graph = (InputGraph) e; - export(writer, graph, previous, true); - previous = graph; - } else if (e instanceof Group) { - export(writer, (Group) e); - } - } - } - - writer.endTag(); - } - - public void export(XMLWriter writer, InputGraph graph, InputGraph previous, boolean difference) throws IOException { - - writer.startTag(Parser.GRAPH_ELEMENT); - writer.writeProperties(graph.getProperties()); - writer.startTag(Parser.NODES_ELEMENT); - - Set removed = new HashSet<>(); - Set equal = new HashSet<>(); - - if (previous != null) { - for (InputNode n : previous.getNodes()) { - int id = n.getId(); - InputNode n2 = graph.getNode(id); - if (n2 == null) { - removed.add(n); - } else if (n.equals(n2)) { - equal.add(n); - } - } - } - - if (difference) { - for (InputNode n : removed) { - writer.simpleTag(Parser.REMOVE_NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, Integer.toString(n.getId()))); - } - } - - for (InputNode n : graph.getNodes()) { - if (!difference || !equal.contains(n)) { - writer.startTag(Parser.NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, Integer.toString(n.getId()))); - writer.writeProperties(n.getProperties()); - writer.endTag(); - } - } - - writer.endTag(); - - writer.startTag(Parser.EDGES_ELEMENT); - Set removedEdges = new HashSet<>(); - Set equalEdges = new HashSet<>(); - - if (previous != null) { - for (InputEdge e : previous.getEdges()) { - if (graph.getEdges().contains(e)) { - equalEdges.add(e); - } else { - removedEdges.add(e); - } - } - } - - if (difference) { - for (InputEdge e : removedEdges) { - writer.simpleTag(Parser.REMOVE_EDGE_ELEMENT, createProperties(e)); - } - } - - for (InputEdge e : graph.getEdges()) { - if (!difference || !equalEdges.contains(e)) { - if (!equalEdges.contains(e)) { - writer.simpleTag(Parser.EDGE_ELEMENT, createProperties(e)); - } - } - } - - writer.endTag(); - - writer.startTag(Parser.CONTROL_FLOW_ELEMENT); - for (InputBlock b : graph.getBlocks()) { - writer.startTag(Parser.BLOCK_ELEMENT, new Properties(Parser.BLOCK_NAME_PROPERTY, b.getName())); - - if (b.getSuccessors().size() > 0) { - writer.startTag(Parser.SUCCESSORS_ELEMENT); - for (InputBlock s : b.getSuccessors()) { - writer.simpleTag(Parser.SUCCESSOR_ELEMENT, new Properties(Parser.BLOCK_NAME_PROPERTY, s.getName())); - } - writer.endTag(); - } - - if (b.getNodes().size() > 0) { - writer.startTag(Parser.NODES_ELEMENT); - for (InputNode n : b.getNodes()) { - writer.simpleTag(Parser.NODE_ELEMENT, new Properties(Parser.NODE_ID_PROPERTY, n.getId() + "")); - } - writer.endTag(); - } - - writer.endTag(); - } - - writer.endTag(); - writer.endTag(); - } - - private void export(XMLWriter w, InputMethod method) throws IOException { - - w.startTag(Parser.METHOD_ELEMENT, new Properties(Parser.METHOD_BCI_PROPERTY, method.getBci() + "", Parser.METHOD_NAME_PROPERTY, method.getName(), Parser.METHOD_SHORT_NAME_PROPERTY, method.getShortName())); - - w.writeProperties(method.getProperties()); - - if (method.getInlined().size() > 0) { - w.startTag(Parser.INLINE_ELEMENT); - for (InputMethod m : method.getInlined()) { - export(w, m); - } - w.endTag(); - } - - w.startTag(Parser.BYTECODES_ELEMENT); - - StringBuilder b = new StringBuilder(); - b.append(""); - w.write(b.toString()); - w.endTag(); - w.endTag(); - } - - private Properties createProperties(InputEdge edge) { - Properties p = new Properties(); - if (edge.getToIndex() != 0) { - p.setProperty(Parser.TO_INDEX_PROPERTY, Integer.toString(edge.getToIndex())); - } - if (edge.getFromIndex() != 0) { - p.setProperty(Parser.FROM_INDEX_PROPERTY, Integer.toString(edge.getFromIndex())); - } - p.setProperty(Parser.TO_PROPERTY, Integer.toString(edge.getTo())); - p.setProperty(Parser.FROM_PROPERTY, Integer.toString(edge.getFrom())); - return p; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLParser.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLParser.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,270 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data.serialization; - -import com.sun.hotspot.igv.data.Properties; -import java.util.HashMap; -import java.util.Stack; -import org.xml.sax.Attributes; -import org.xml.sax.ContentHandler; -import org.xml.sax.Locator; -import org.xml.sax.SAXException; - -/** - * - * @author Thomas Wuerthinger - */ -public class XMLParser implements ContentHandler { - - public static interface ParseMonitor { - - public void setProgress(double d); - - public void setState(String state); - } - - public static class MissingAttributeException extends SAXException { - - private String name; - - public MissingAttributeException(String name) { - super("Missing attribute \"" + name + "\""); - this.name = name; - } - - public String getAttributeName() { - return this.getMessage(); - } - } - - public static class HandoverElementHandler

extends ElementHandler { - - @Override - protected P start() throws SAXException { - return getParentObject(); - } - - public HandoverElementHandler(String name) { - super(name); - } - - public HandoverElementHandler(String name, boolean needsText) { - super(name, needsText); - } - } - - public static class TopElementHandler

extends ElementHandler { - - public TopElementHandler() { - super(null); - } - } - - public static class ElementHandler { - - private String name; - private Stack object = new Stack<>(); - private Attributes attr; - private StringBuilder currentText; - private ParseMonitor monitor; - private HashMap> hashtable; - private boolean needsText; - private Stack> parentElement = new Stack<>(); - private Stack

parentObject = new Stack<>(); - - public ElementHandler(String name) { - this(name, false); - } - - public ElementHandler getParentElement() { - return parentElement.peek(); - } - - public P getParentObject() { - return parentObject.peek(); - } - - protected boolean needsText() { - return needsText; - } - - public ElementHandler(String name, boolean needsText) { - this.hashtable = new HashMap<>(); - this.name = name; - this.needsText = needsText; - } - - public ParseMonitor getMonitor() { - return monitor; - } - - public ElementHandler getChild(String name) { - return hashtable.get(name); - } - - public void addChild(ElementHandler handler) { - assert handler != null; - hashtable.put(handler.getName(), handler); - } - - public String getName() { - return name; - } - - public T getObject() { - return object.size() == 0 ? null : object.peek(); - } - - public String readAttribute(String name) { - return attr.getValue(name); - } - - public String readRequiredAttribute(String name) throws SAXException { - String s = readAttribute(name); - if (s == null) { - throw new MissingAttributeException(name); - } - return s; - } - - public void processAttributesAsProperties(Properties p) { - int length = attr.getLength(); - for (int i = 0; i < length; i++) { - String val = attr.getValue(i); - String localName = attr.getLocalName(i); - p.setProperty(val, localName); - } - } - - public void startElement(ElementHandler parentElement, Attributes attr, ParseMonitor monitor) throws SAXException { - this.currentText = new StringBuilder(); - this.attr = attr; - this.monitor = monitor; - this.parentElement.push(parentElement); - parentObject.push(parentElement.getObject()); - object.push(start()); - } - - protected T start() throws SAXException { - return null; - } - - protected void end(String text) throws SAXException { - - } - - public void endElement() throws SAXException { - end(currentText.toString()); - object.pop(); - parentElement.pop(); - parentObject.pop(); - } - - protected void text(char[] c, int start, int length) { - assert currentText != null; - currentText.append(c, start, length); - } - } - private Stack stack; - private ParseMonitor monitor; - - public XMLParser(TopElementHandler rootHandler, ParseMonitor monitor) { - this.stack = new Stack<>(); - this.monitor = monitor; - this.stack.push(rootHandler); - } - - @Override - public void setDocumentLocator(Locator locator) { - if (monitor != null) { - monitor.setState("Starting parsing"); - } - } - - @Override - public void startDocument() throws SAXException { - } - - @Override - public void endDocument() throws SAXException { - } - - @Override - public void startPrefixMapping(String prefix, String uri) throws SAXException { - } - - @Override - public void endPrefixMapping(String prefix) throws SAXException { - } - - @SuppressWarnings("unchecked") - @Override - public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { - assert !stack.isEmpty(); - - ElementHandler parent = stack.peek(); - if (parent != null) { - ElementHandler child = parent.getChild(qName); - if (child != null) { - child.startElement(parent, atts, monitor); - stack.push(child); - return; - } - } - - stack.push(null); - } - - @Override - public void endElement(String uri, String localName, String qName) throws SAXException { - ElementHandler handler = stack.pop(); - if (handler != null) { - handler.endElement(); - } - } - - @Override - public void characters(char[] ch, int start, int length) throws SAXException { - - assert !stack.isEmpty(); - - - ElementHandler top = stack.peek(); - if (top != null && top.needsText()) { - top.text(ch, start, length); - } - } - - @Override - public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { - } - - @Override - public void processingInstruction(String target, String data) throws SAXException { - } - - @Override - public void skippedEntity(String name) throws SAXException { - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLWriter.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/serialization/XMLWriter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -/* - * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 com.sun.hotspot.igv.data.serialization; - -import com.sun.hotspot.igv.data.Properties; -import com.sun.hotspot.igv.data.Property; -import java.io.IOException; -import java.io.Writer; -import java.util.Stack; - -/** - * - * @author Thomas Wuerthinger - */ -public class XMLWriter extends Writer { - - private Writer inner; - private Stack elementStack; - - public XMLWriter(Writer inner) { - this.inner = inner; - elementStack = new Stack<>(); - } - - @Override - public void write(char[] arr) throws IOException { - write(arr, 0, arr.length); - } - - @Override - public void write(char[] cbuf, int off, int len) throws IOException { - for (int i = off; i < off + len; i++) { - char c = cbuf[i]; - if (c == '>') { - inner.write(">"); - } else if (c == '<') { - inner.write("<"); - } else if (c == '&') { - inner.write("&"); - } else { - inner.write(c); - } - } - } - - @Override - public void flush() throws IOException { - inner.flush(); - } - - @Override - public void close() throws IOException { - inner.close(); - } - - public void endTag() throws IOException { - inner.write("\n"); - } - - public void startTag(String name) throws IOException { - inner.write("<" + name + ">\n"); - elementStack.push(name); - } - - public void simpleTag(String name) throws IOException { - inner.write("<" + name + "/>\n"); - } - - public void startTag(String name, Properties attributes) throws IOException { - inner.write("<" + name); - elementStack.push(name); - - for (Property p : attributes) { - inner.write(" " + p.getName() + "=\""); - write(p.getValue().toCharArray()); - inner.write("\""); - } - - inner.write(">\n"); - } - - public void simpleTag(String name, Properties attributes) throws IOException { - inner.write("<" + name); - - for (Property p : attributes) { - inner.write(" " + p.getName() + "=\""); - write(p.getValue().toCharArray()); - inner.write("\""); - } - - inner.write("/>\n"); - } - - public void writeProperties(Properties props) throws IOException { - if (props.iterator().hasNext() == false) { - return; - } - - startTag(Parser.PROPERTIES_ELEMENT); - - for (Property p : props) { - startTag(Parser.PROPERTY_ELEMENT, new Properties(Parser.PROPERTY_NAME_PROPERTY, p.getName())); - this.write(p.getValue().toCharArray()); - endTag(); - } - - endTag(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/serialization/graphdocument.xsd --- a/visualizer/Data/src/com/sun/hotspot/igv/data/serialization/graphdocument.xsd Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,146 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/services/GraphViewer.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/services/GraphViewer.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.data.services; - -import com.sun.hotspot.igv.data.InputGraph; - -/** - * - * @author Thomas Wuerthinger - */ -public interface GraphViewer { - - public void view(InputGraph graph); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/services/GroupCallback.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/services/GroupCallback.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 com.sun.hotspot.igv.data.services; - -import com.sun.hotspot.igv.data.Group; - -/** - * - * @author Thomas Wuerthinger - */ -public interface GroupCallback { - - public void started(Group g); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/services/InputGraphProvider.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/services/InputGraphProvider.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -/* - * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 com.sun.hotspot.igv.data.services; - -import com.sun.hotspot.igv.data.InputGraph; -import com.sun.hotspot.igv.data.InputNode; -import java.util.Set; - -/** - * - * @author Thomas Wuerthinger - */ -public interface InputGraphProvider { - - InputGraph getGraph(); - - void setSelectedNodes(Set nodes); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/src/com/sun/hotspot/igv/data/services/Scheduler.java --- a/visualizer/Data/src/com/sun/hotspot/igv/data/services/Scheduler.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/* - * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 com.sun.hotspot.igv.data.services; - -import com.sun.hotspot.igv.data.InputBlock; -import com.sun.hotspot.igv.data.InputGraph; -import java.util.Collection; - -/** - * - * @author Thomas Wuerthinger - */ -public interface Scheduler { - - public Collection schedule(InputGraph graph); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/ChangedEventTest.java --- a/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/ChangedEventTest.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.sun.hotspot.igv.data; - -import static org.junit.Assert.assertEquals; -import org.junit.*; - -/** - * - * @author Thomas Wuerthinger - */ -public class ChangedEventTest { - - public ChangedEventTest() { - } - - @BeforeClass - public static void setUpClass() throws Exception { - } - - @AfterClass - public static void tearDownClass() throws Exception { - } - - @Before - public void setUp() { - } - - @After - public void tearDown() { - } - - /** - * Test of addListener method, of class Event. - */ - @Test - public void testBase() { - - ChangedEvent e = new ChangedEvent<>(5); - final int[] fireCount = new int[1]; - - e.addListener(new ChangedListener() { - @Override - public void changed(Integer s) { - assertEquals(s.intValue(), 5); - fireCount[0]++; - } - }); - - e.fire(); - assertEquals(1, fireCount[0]); - - e.fire(); - assertEquals(2, fireCount[0]); - - e.beginAtomic(); - - e.fire(); - assertEquals(2, fireCount[0]); - - e.fire(); - assertEquals(2, fireCount[0]); - - e.fire(); - assertEquals(2, fireCount[0]); - - e.endAtomic(); - assertEquals(3, fireCount[0]); - - } - - -} \ No newline at end of file diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/ControllableChangedListenerTest.java --- a/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/ControllableChangedListenerTest.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.sun.hotspot.igv.data; - -import static org.junit.Assert.*; -import org.junit.*; - -/** - * - * @author Thomas Wuerthinger - */ -public class ControllableChangedListenerTest { - - public ControllableChangedListenerTest() { - } - - @BeforeClass - public static void setUpClass() throws Exception { - } - - @AfterClass - public static void tearDownClass() throws Exception { - } - - @Before - public void setUp() { - } - - @After - public void tearDown() { - } - - /** - * Test of isEnabled method, of class ControllableChangedListener. - */ - @Test - public void testBase() { - - final boolean[] hasFired = new boolean[1]; - final boolean[] shouldFire = new boolean[1]; - final Integer[] valueToFire = new Integer[1]; - ControllableChangedListener l = new ControllableChangedListener() { - - @Override - public void filteredChanged(Integer value) { - assertTrue(shouldFire[0]); - assertEquals(valueToFire[0], value); - hasFired[0] = true; - } - }; - - shouldFire[0] = true; - valueToFire[0] = 1; - hasFired[0] = false; - l.changed(1); - assertTrue(hasFired[0]); - - shouldFire[0] = false; - hasFired[0] = false; - l.setEnabled(false); - l.changed(1); - assertFalse(hasFired[0]); - - shouldFire[0] = true; - valueToFire[0] = 1; - hasFired[0] = false; - l.setEnabled(true); - l.changed(1); - assertTrue(hasFired[0]); - } -} \ No newline at end of file diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/GroupTest.java --- a/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/GroupTest.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.sun.hotspot.igv.data; - -import java.util.Arrays; -import java.util.HashSet; -import static org.junit.Assert.assertEquals; -import org.junit.*; - -/** - * - * @author Thomas Wuerthinger - */ -public class GroupTest { - - public GroupTest() { - } - - @BeforeClass - public static void setUpClass() throws Exception { - - } - - @AfterClass - public static void tearDownClass() throws Exception { - } - - @Before - public void setUp() { - } - - @After - public void tearDown() { - } - - /** - * Test of getAllNodes method, of class Group. - */ - @Test - public void testGetAllNodes() { - final Group g = new Group(null); - final InputGraph graph1 = new InputGraph("1"); - final InputGraph graph2 = new InputGraph("2"); - g.addElement(graph1); - g.addElement(graph2); - graph1.addNode(new InputNode(1)); - graph1.addNode(new InputNode(2)); - graph2.addNode(new InputNode(2)); - graph2.addNode(new InputNode(3)); - assertEquals(g.getAllNodes(), new HashSet(Arrays.asList(1, 2, 3))); - } -} \ No newline at end of file diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/InputGraphTest.java --- a/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/InputGraphTest.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,211 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.sun.hotspot.igv.data; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import org.junit.*; - -/** - * - * @author Thomas Wuerthinger - */ -public class InputGraphTest { - - /** - * 1 - * / \ - * 2 3 - * \ | 5 - * \ | / - * 4 - */ - private static InputGraph referenceGraph; - - private static InputGraph emptyGraph; - - private static final InputNode N1 = new InputNode(1); - private static final InputNode N2 = new InputNode(2); - private static final InputNode N3 = new InputNode(3); - private static final InputNode N4 = new InputNode(4); - private static final InputNode N5 = new InputNode(5); - private static final InputEdge E12 = new InputEdge((char)0, 1, 2); - private static final InputEdge E13 = new InputEdge((char)0, 1, 3); - private static final InputEdge E24 = new InputEdge((char)0, 2, 4); - private static final InputEdge E34 = new InputEdge((char)0, 3, 4); - private static final InputEdge E54 = new InputEdge((char)0, 5, 4); - - public InputGraphTest() { - } - - @BeforeClass - public static void setUpClass() throws Exception { - Group group = new Group(null); - - emptyGraph = new InputGraph("emptyGraph"); - group.addElement(emptyGraph); - - referenceGraph = new InputGraph("referenceGraph"); - group.addElement(referenceGraph); - referenceGraph.addNode(N1); - referenceGraph.addNode(N2); - referenceGraph.addNode(N3); - referenceGraph.addNode(N4); - referenceGraph.addNode(N5); - - referenceGraph.addEdge(E12); - referenceGraph.addEdge(E13); - referenceGraph.addEdge(E24); - referenceGraph.addEdge(E34); - referenceGraph.addEdge(E54); - } - - @AfterClass - public static void tearDownClass() throws Exception { - } - - @Before - public void setUp() { - } - - @After - public void tearDown() { - } - - /** - * Test of equals method, of class InputGraph. - */ - @Test - public void testEquals() { - - Group parentA = new Group(null); - InputGraph a = new InputGraph("graph"); - parentA.addElement(a); - - Group parentB = new Group(null); - InputGraph b = new InputGraph("graph"); - parentB.addElement(b); - - InputGraph c = new InputGraph("graph"); - parentB.addElement(b); - - Util.assertGraphEquals(a, b); - Util.assertGraphEquals(b, c); - - a.addNode(new InputNode(1)); - Util.assertGraphNotEquals(a, b); - - b.addNode(new InputNode(1)); - Util.assertGraphEquals(a, b); - } - - /** - * Test of findRootNodes method, of class InputGraph. - */ - @Test - public void testFindRootNodes() { - assertTrue(emptyGraph.findRootNodes().isEmpty()); - - List result = referenceGraph.findRootNodes(); - assertTrue(result.size() == 2); - assertTrue(result.contains(N1)); - assertTrue(result.contains(N5)); - } - - /** - * Test of findAllOutgoingEdges method, of class InputGraph. - */ - @Test - public void testFindAllOutgoingEdges() { - assertTrue(emptyGraph.findAllOutgoingEdges().isEmpty()); - - Map> result = referenceGraph.findAllOutgoingEdges(); - assertTrue(result.size() == 5); - assertEquals(result.get(N1), Arrays.asList(E12, E13)); - assertEquals(result.get(N2), Arrays.asList(E24)); - assertEquals(result.get(N3), Arrays.asList(E34)); - assertEquals(result.get(N4), Arrays.asList()); - assertEquals(result.get(N5), Arrays.asList(E54)); - } - - /** - * Test of findAllIngoingEdges method, of class InputGraph. - */ - @Test - public void testFindAllIngoingEdges() { - assertTrue(emptyGraph.findAllIngoingEdges().isEmpty()); - - Map> result = referenceGraph.findAllIngoingEdges(); - assertTrue(result.size() == 5); - assertEquals(result.get(N1), Arrays.asList()); - assertEquals(result.get(N2), Arrays.asList(E12)); - assertEquals(result.get(N3), Arrays.asList(E13)); - assertEquals(result.get(N4), Arrays.asList(E24, E34, E54)); - assertEquals(result.get(N5), Arrays.asList()); - } - - /** - * Test of findOutgoingEdges method, of class InputGraph. - */ - @Test - public void testFindOutgoingEdges() { - assertTrue(emptyGraph.findOutgoingEdges(new InputNode(1)).isEmpty()); - - assertEquals(referenceGraph.findOutgoingEdges(N1), Arrays.asList(E12, E13)); - assertEquals(referenceGraph.findOutgoingEdges(N2), Arrays.asList(E24)); - assertEquals(referenceGraph.findOutgoingEdges(N3), Arrays.asList(E34)); - assertEquals(referenceGraph.findOutgoingEdges(N4), Arrays.asList()); - assertEquals(referenceGraph.findOutgoingEdges(N5), Arrays.asList(E54)); - } - - /** - * Test of getNext method, of class InputGraph. - */ - @Test - public void testGetNextPrev() { - final Group group = new Group(null); - - final InputGraph a = new InputGraph("a"); - - final InputGraph b = new InputGraph("b"); - - final InputGraph c = new InputGraph("c"); - group.addElement(a); - group.addElement(b); - group.addElement(c); - - assertEquals(null, a.getPrev()); - assertEquals(b, a.getNext()); - - assertEquals(a, b.getPrev()); - assertEquals(c, b.getNext()); - - assertEquals(b, c.getPrev()); - assertEquals(null, c.getNext()); - } -} \ No newline at end of file diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/InputMethodTest.java --- a/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/InputMethodTest.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.sun.hotspot.igv.data; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.junit.Assert.assertThat; -import org.junit.*; - -/** - * - * @author Thomas - */ -public class InputMethodTest { - - public InputMethodTest() { - } - - @BeforeClass - public static void setUpClass() throws Exception { - } - - @AfterClass - public static void tearDownClass() throws Exception { - } - - @Before - public void setUp() { - } - - @After - public void tearDown() { - } - - - /** - * Test of getBytecodes method, of class InputMethod. - */ - @Test - public void testGetSetBytecodes() { - - final String input = "0 iload_0\n" + - "1 iconst_1\n" + - "2 if_icmpne 7\n" + - "5 iconst_1\n" + - "6 ireturn\n" + - "7 iconst_0\n" + - "8 ireturn"; - - final Group g = new Group(null); - InputMethod m = new InputMethod(g, "name", "shortName", -1); - m.setBytecodes(input); - - assertThat(m.getBytecodes().size(), is(7)); - - assertThat(m.getBytecodes().get(0).getBci(), is(0)); - assertThat(m.getBytecodes().get(1).getBci(), is(1)); - assertThat(m.getBytecodes().get(2).getBci(), is(2)); - assertThat(m.getBytecodes().get(3).getBci(), is(5)); - - assertThat(m.getBytecodes().get(0).getName(), is("iload_0")); - assertThat(m.getBytecodes().get(1).getName(), is("iconst_1")); - assertThat(m.getBytecodes().get(2).getName(), is("if_icmpne 7")); - assertThat(m.getBytecodes().get(6).getName(), is("ireturn")); - - assertThat(m.getBytecodes().get(2).getInlined(), nullValue()); - assertThat(m.getBytecodes().get(6).getInlined(), nullValue()); - } - - -} \ No newline at end of file diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PairTest.java --- a/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PairTest.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -/* - * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 com.sun.hotspot.igv.data; - -import static org.junit.Assert.*; -import org.junit.*; - -/** - * - * @author Thomas Wuerthinger - */ -public class PairTest { - - public PairTest() { - } - - @BeforeClass - public static void setUpClass() throws Exception { - } - - @AfterClass - public static void tearDownClass() throws Exception { - } - - @Before - public void setUp() { - } - - @After - public void tearDown() { - } - - /** - * Test of getLeft method, of class Pair. - */ - @Test - public void testBase() { - Pair p = new Pair(); - assertTrue(p.getLeft() == null); - assertTrue(p.getRight() == null); - assertEquals("[null/null]", p.toString()); - assertFalse(p.equals(null)); - - Pair p2 = new Pair(1, 2); - assertTrue(p2.getLeft().intValue() == 1); - assertTrue(p2.getRight().intValue() == 2); - assertFalse(p.equals(p2)); - assertFalse(p2.equals(p)); - assertFalse(p.hashCode() == p2.hashCode()); - assertEquals("[1/2]", p2.toString()); - - Pair p3 = new Pair(1, 2); - assertTrue(p2.equals(p3)); - assertTrue(p2.hashCode() == p3.hashCode()); - - p2.setLeft(2); - assertFalse(p2.equals(p3)); - assertTrue(p2.getLeft().intValue() == 2); - assertTrue(p2.getRight().intValue() == 2); - assertFalse(p2.hashCode() == p3.hashCode()); - assertEquals("[2/2]", p2.toString()); - - p2.setRight(1); - assertFalse(p2.equals(p3)); - assertTrue(p2.getLeft().intValue() == 2); - assertTrue(p2.getRight().intValue() == 1); - assertFalse(p2.hashCode() == p3.hashCode()); - assertEquals("[2/1]", p2.toString()); - - p3.setLeft(2); - p3.setRight(1); - assertTrue(p2.hashCode() == p3.hashCode()); - assertTrue(p2.equals(p3)); - } -} \ No newline at end of file diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PropertiesTest.java --- a/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PropertiesTest.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,401 +0,0 @@ -/* - * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 com.sun.hotspot.igv.data; - -import com.sun.hotspot.igv.data.Properties.InvertPropertyMatcher; -import com.sun.hotspot.igv.data.Properties.PropertyMatcher; -import com.sun.hotspot.igv.data.Properties.PropertySelector; -import com.sun.hotspot.igv.data.Properties.RegexpPropertyMatcher; -import com.sun.hotspot.igv.data.Properties.StringPropertyMatcher; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import junit.framework.TestCase; - -/** - * - * @author Thomas Wuerthinger - */ -public class PropertiesTest extends TestCase { - - - - public PropertiesTest(String testName) { - super(testName); - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - /** - * Test of equals method, of class Properties. - */ - public void testEquals() { - Properties a = new Properties(); - assertFalse(a.equals(null)); - assertTrue(a.equals(a)); - - Properties b = new Properties(); - assertTrue(a.equals(b)); - assertTrue(a.hashCode() == b.hashCode()); - - a.setProperty("p1", "1"); - assertFalse(a.equals(b)); - assertFalse(b.equals(a)); - assertFalse(a.hashCode() == b.hashCode()); - - b.setProperty("p1", "1"); - assertTrue(a.equals(b)); - assertTrue(a.hashCode() == b.hashCode()); - - Properties c = new Properties(a); - assertTrue(c.equals(a)); - assertTrue(c.equals(b)); - - c.setProperty("p1", "2"); - assertFalse(c.equals(b)); - assertFalse(c.hashCode() == b.hashCode()); - assertFalse(c.equals(a)); - assertFalse(c.hashCode() == a.hashCode()); - - a.setProperty("p2", "2"); - Properties d = new Properties(); - d.setProperty("p2", "2"); - d.setProperty("p1", "1"); - assertTrue(d.equals(a)); - } - - /** - * Test of selectSingle method, of class Properties. - */ - public void testSelectSingle() { - - final boolean[] called = new boolean[1]; - final String v = "2"; - final String n = "p2"; - - PropertyMatcher matcher = new PropertyMatcher() { - - @Override - public String getName() { - assertFalse(called[0]); - called[0] = true; - return n; - } - - @Override - public boolean match(String value) { - assertTrue(v.equals(value)); - return true; - } - }; - - Properties instance = new Properties(); - instance.setProperty("p1", "1"); - instance.setProperty(n, v); - instance.setProperty("p3", "3"); - Property result = instance.selectSingle(matcher); - assertEquals(result, new Property(n, v)); - - - called[0] = false; - PropertyMatcher matcher2 = new PropertyMatcher() { - - @Override - public String getName() { - assertFalse(called[0]); - called[0] = true; - return n; - } - - @Override - public boolean match(String value) { - return false; - } - }; - - - Property result2 = instance.selectSingle(matcher2); - assertTrue(result2 == null); - } - - /** - * Test of get method, of class Properties. - */ - public void testGet() { - Properties instance = new Properties(); - instance.setProperty("p1", "1"); - assertEquals("1", instance.get("p1")); - assertEquals(null, instance.get("p2")); - } - - /** - * Test of getProperties method, of class Properties. - */ - public void testIterator() { - Properties instance = new Properties(); - instance.setProperty("p1", "1"); - instance.setProperty("p2", "2"); - Iterator result = instance.iterator(); - assertTrue(result.hasNext()); - assertEquals(new Property("p1", "1"), result.next()); - assertTrue(result.hasNext()); - assertEquals(new Property("p2", "2"), result.next()); - assertFalse(result.hasNext()); - assertTrue(result.next() == null); - - try { - result.remove(); - fail(); - } catch(UnsupportedOperationException e) {} - } - - /** - * Test of add method, of class Properties. - */ - public void testAdd() { - Properties a = new Properties(); - a.setProperty("p1", "1"); - a.setProperty("p2", "2"); - - Properties b = new Properties(); - b.setProperty("p1", "1"); - - Properties c = new Properties(); - c.setProperty("p2", "2"); - - assertFalse(a.equals(b)); - b.add(c); - - assertTrue(a.equals(b)); - - b.setProperty("p3", null); - assertTrue(a.equals(b)); - - Properties empty = new Properties(); - b.add(empty); - assertTrue(a.equals(b)); - - empty.add(b); - assertTrue(a.equals(empty)); - } - - - /** - * Test the multiple argument constructors. - */ - public void testConstructors() { - Properties a = new Properties("p1", "1", "p2", "2", "p3", "3"); - Properties b = new Properties("p1", "1", "p2", "2"); - Properties c = new Properties("p1", "1"); - - assertTrue(a.get("p3").equals("3")); - assertTrue(b.get("p2").equals("2")); - assertTrue(b.get("p1").equals("1")); - - b.setProperty("p3", "3"); - c.setProperty("p2", "2"); - c.setProperty("p3", "3"); - - assertTrue(a.equals(b)); - assertTrue(a.equals(c)); - } - - /** - * Test Entity class - */ - public void testEntity() { - - Properties p = new Properties(); - - Properties.Entity entity = new Properties.Entity(); - assertEquals(entity.getProperties(), p); - - entity.getProperties().setProperty("p1", "1"); - Properties.Entity entity2 = new Properties.Entity(entity); - assertEquals(entity.getProperties(), entity2.getProperties()); - } - - /** - * Test property selector - */ - public void testPropertySelector() { - final Collection c = new ArrayList<>(); - - final Properties.Entity e1 = new Properties.Entity(); - e1.getProperties().setProperty("p1", "1"); - e1.getProperties().setProperty("p2", "2"); - c.add(e1); - - final Properties.Entity e2 = new Properties.Entity(); - e2.getProperties().setProperty("p2", "2"); - e2.getProperties().setProperty("p1", "1"); - e2.getProperties().setProperty("p3", "3"); - c.add(e2); - - final Properties.Entity e3 = new Properties.Entity(); - e3.getProperties().setProperty("p3", "3"); - e3.getProperties().setProperty("p4", "4"); - c.add(e3); - - final PropertySelector sel = new PropertySelector<>(c); - - final StringPropertyMatcher matcher1 = new StringPropertyMatcher("p2", "2"); - assertTrue(sel.selectMultiple(matcher1).size() == 2); - assertTrue(sel.selectMultiple(matcher1).contains(e1)); - assertTrue(sel.selectMultiple(matcher1).contains(e2)); - assertTrue(sel.selectSingle(matcher1).equals(e1) || sel.selectSingle(matcher1).equals(e2)); - - final StringPropertyMatcher matcher2 = new StringPropertyMatcher("p3", "3"); - assertTrue(sel.selectMultiple(matcher2).size() == 2); - assertTrue(sel.selectMultiple(matcher2).contains(e2)); - assertTrue(sel.selectMultiple(matcher2).contains(e3)); - assertTrue(sel.selectSingle(matcher2).equals(e2) || sel.selectSingle(matcher2).equals(e3)); - - final StringPropertyMatcher matcher3 = new StringPropertyMatcher("p4", "4"); - assertTrue(sel.selectMultiple(matcher3).size() == 1); - assertTrue(sel.selectMultiple(matcher3).contains(e3)); - assertTrue(sel.selectSingle(matcher3).equals(e3)); - - final StringPropertyMatcher matcher4 = new StringPropertyMatcher("p5", "5"); - assertTrue(sel.selectMultiple(matcher4).size() == 0); - assertTrue(sel.selectSingle(matcher4) == null); - } - - public void testRemoveProperty() { - final Properties p = new Properties(); - p.setProperty("p1", "1"); - p.setProperty("p2", "2"); - - assertTrue(p.get("p1").equals("1")); - assertTrue(p.get("p2").equals("2")); - - p.setProperty("p1", null); - assertTrue(p.get("p1") == null); - assertTrue(p.get("p2").equals("2")); - - p.setProperty("p2", null); - assertTrue(p.get("p1") == null); - assertTrue(p.get("p2") == null); - - p.setProperty("p3", "3"); - assertTrue(p.get("p1") == null); - assertTrue(p.get("p2") == null); - assertTrue(p.get("p3").equals("3")); - } - - /** - * Test property matchers - */ - public void testPropertyMatchers() { - final StringPropertyMatcher matcher = new StringPropertyMatcher("p1", "1"); - assertTrue(matcher.getName().equals("p1")); - assertTrue(matcher.match("1")); - assertFalse(matcher.match("2")); - try { - matcher.match(null); - fail(); - } catch(IllegalArgumentException e) {} - - try { - new StringPropertyMatcher(null, "**"); - fail(); - } catch(IllegalArgumentException e) {} - - try { - new StringPropertyMatcher("p1", null); - fail(); - } catch(IllegalArgumentException e) {} - - final RegexpPropertyMatcher matcher2 = new RegexpPropertyMatcher("p1", "C.*"); - assertTrue(matcher2.getName().equals("p1")); - assertTrue(matcher2.match("C")); - assertTrue(matcher2.match("Casdf")); - assertFalse(matcher2.match(" C")); - assertFalse(matcher2.match("c")); - assertFalse(matcher2.match("asdfC")); - - try { - matcher2.match(null); - fail(); - } catch(IllegalArgumentException e) {} - - try { - new RegexpPropertyMatcher("p1", "**"); - fail(); - } catch(IllegalArgumentException e) {} - - try { - new RegexpPropertyMatcher(null, "1"); - fail(); - } catch(IllegalArgumentException e) {} - - try { - new RegexpPropertyMatcher("p1", null); - fail(); - } catch(IllegalArgumentException e) {} - - final InvertPropertyMatcher matcher3 = new InvertPropertyMatcher(matcher); - assertTrue(matcher3.getName().equals("p1")); - assertFalse(matcher3.match("1")); - assertTrue(matcher3.match("2")); - assertFalse(matcher3.match(null)); - } - - public void testToString() { - Properties p = new Properties(); - assertEquals(p.toString(), "[]"); - - p.setProperty("p1", "1"); - assertEquals(p.toString(), "[p1=1]"); - - Properties p2 = new Properties(); - p2.setProperty("p1", "1"); - p2.setProperty("p2", "2"); - assertEquals(p2.toString(), "[p1=1, p2=2]"); - - Properties p3 = new Properties(); - p3.setProperty("p2", "2"); - p3.setProperty("p1", "1"); - assertEquals(p3.toString(), "[p1=1, p2=2]"); - - p3.setProperty("p0", "0"); - assertEquals(p3.toString(), "[p0=0, p1=1, p2=2]"); - - p2.setProperty("p1", null); - assertEquals(p2.toString(), "[p2=2]"); - - p2.setProperty("p2", null); - assertEquals(p2.toString(), "[]"); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PropertyTest.java --- a/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/PropertyTest.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -/* - * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 com.sun.hotspot.igv.data; - -import static org.junit.Assert.*; -import org.junit.*; - -/** - * - * @author Thomas Wuerthinger - */ -public class PropertyTest { - - public PropertyTest() { - } - - @BeforeClass - public static void setUpClass() throws Exception { - } - - @AfterClass - public static void tearDownClass() throws Exception { - } - - @Before - public void setUp() { - } - - @After - public void tearDown() { - } - - /** - * Test of getName method, of class Property. - */ - @Test - public void testGetNameAndValue() { - final Property p = new Property("name", "value"); - assertEquals(p.getName(), "name"); - assertEquals(p.getValue(), "value"); - - try { - new Property(null, "value"); - fail(); - } catch(IllegalArgumentException e) { - } - - - try { - new Property("name", null); - fail(); - } catch(IllegalArgumentException e) { - } - } - - /** - * Test of toString method, of class Property. - */ - @Test - public void testToString() { - final Property p = new Property("name", "value"); - assertEquals(p.toString(), "name=value"); - } - - /** - * Test of equals method, of class Property. - */ - @Test - public void testEquals() { - final Property p = new Property("name", "value"); - final Object o = new Object(); - assertFalse(p.equals(o)); - assertFalse(p.equals(null)); - assertTrue(p.equals(p)); - - final Property p2 = new Property("name", "value1"); - assertFalse(p.equals(p2)); - assertTrue(p.hashCode() != p2.hashCode()); - - final Property p3 = new Property("name2", "value"); - assertFalse(p.equals(p3)); - assertTrue(p.hashCode() != p3.hashCode()); - assertTrue(p2.hashCode() != p3.hashCode()); - - final Property p4 = new Property("name", "value"); - assertEquals(p, p4); - assertEquals(p.hashCode(), p4.hashCode()); - - final Property p5 = new Property("value", "name"); - assertFalse(p.equals(p5)); - assertTrue(p.hashCode() != p5.hashCode()); - } -} \ No newline at end of file diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/SourceTest.java --- a/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/SourceTest.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.sun.hotspot.igv.data; - -import java.util.Arrays; -import java.util.LinkedHashSet; -import static org.junit.Assert.assertEquals; -import org.junit.*; - -/** - * - * @author Thomas - */ -public class SourceTest { - - public SourceTest() { - } - - @BeforeClass - public static void setUpClass() throws Exception { - } - - @AfterClass - public static void tearDownClass() throws Exception { - } - - @Before - public void setUp() { - } - - @After - public void tearDown() { - } - - /** - * Test of getSourceNodes method, of class Source. - */ - @Test - public void testBase() { - final Source s = new Source(); - - final InputNode N1 = new InputNode(1); - final InputNode N2 = new InputNode(2); - - s.addSourceNode(N1); - assertEquals(s.getSourceNodes(), Arrays.asList(N1)); - assertEquals(s.getSourceNodesAsSet(), new LinkedHashSet<>(Arrays.asList(1))); - - s.addSourceNode(N2); - assertEquals(s.getSourceNodes(), Arrays.asList(N1, N2)); - assertEquals(s.getSourceNodesAsSet(), new LinkedHashSet<>(Arrays.asList(1, 2))); - - s.addSourceNode(N1); - assertEquals(s.getSourceNodes(), Arrays.asList(N1, N2)); - assertEquals(s.getSourceNodesAsSet(), new LinkedHashSet<>(Arrays.asList(1, 2))); - } -} \ No newline at end of file diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/Util.java --- a/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/Util.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -/* - * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 com.sun.hotspot.igv.data; - -import static org.junit.Assert.*; - -/** - * - * @author Thomas Wuerthinger - */ -public class Util { - - public static void assertGraphDocumentNotEquals(GraphDocument a, GraphDocument b) { - try { - assertGraphDocumentEquals(a, b); - } catch(AssertionError e) { - return; - } - - fail("Graphs documents are equal!"); - } - - public static void assertGraphDocumentEquals(GraphDocument a, GraphDocument b) { - - if (a.getElements().size() != b.getElements().size()) { - fail(); - } - - int z = 0; - for (FolderElement e : b.getElements()) { - - if (e instanceof Group) { - Group g = (Group) e; - Group thisG = (Group) a.getElements().get(z); - assertGroupEquals(thisG, g); - z++; - } - } - } - - public static void assertGroupNotEquals(Group a, Group b) { - try { - assertGroupEquals(a, b); - } catch(AssertionError e) { - return; - } - - fail("Groups are equal!"); - } - - public static void assertGroupEquals(Group a, Group b) { - - if (a.getGraphsCount() != b.getGraphsCount()) { - fail(); - } - - int z = 0; - for (InputGraph graph : a.getGraphs()) { - InputGraph otherGraph = b.getGraphs().get(z); - assertGraphEquals(graph, otherGraph); - z++; - } - - if (a.getMethod() == null || b.getMethod() == null) { - if (a.getMethod() != b.getMethod()) { - fail(); - } - } else { - if (!a.getMethod().equals(b.getMethod())) { - fail(); - } - } - } - - public static void assertGraphNotEquals(InputGraph a, InputGraph b) { - try { - assertGraphEquals(a, b); - } catch(AssertionError e) { - return; - } - - fail("Graphs are equal!"); - } - - public static void assertGraphEquals(InputGraph a, InputGraph b) { - - if(!a.getNodesAsSet().equals(b.getNodesAsSet())) { - fail(); - } - - if (!a.getEdges().equals(b.getEdges())) { - fail(); - } - - if (a.getBlocks().equals(b.getBlocks())) { - fail(); - } - - for (InputNode n : a.getNodes()) { - assertEquals(a.getBlock(n), b.getBlock(n)); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/serialization/ParserTest.java --- a/visualizer/Data/test/unit/src/com/sun/hotspot/igv/data/serialization/ParserTest.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,223 +0,0 @@ -/* - * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 com.sun.hotspot.igv.data.serialization; - -import com.sun.hotspot.igv.data.*; -import java.io.CharArrayWriter; -import java.io.StringReader; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; -import org.junit.*; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -/** - * - * @author Thomas Wuerthinger - */ -public class ParserTest { - - public ParserTest() { - } - - @BeforeClass - public static void setUpClass() throws Exception { - } - - @AfterClass - public static void tearDownClass() throws Exception { - } - - @Before - public void setUp() { - } - - @After - public void tearDown() { - } - - private void test(GraphDocument document) { - final Printer printer = new Printer(); - final CharArrayWriter writer = new CharArrayWriter(); - printer.export(writer, document); - test(document, writer.toString()); - } - - private void test(GraphDocument document, String xmlString) { - - StringReader sr = new StringReader(xmlString); - InputSource is = new InputSource(sr); - - try { - Parser parser = new Parser(); - final GraphDocument parsedDocument = parser.parse(is, null); - Util.assertGraphDocumentEquals(document, parsedDocument); - } catch (SAXException ex) { - fail(ex.toString()); - } - } - - private void testBoth(GraphDocument document, String xmlString) { - test(document); - test(document, xmlString); - } - - /** - * Test of graph document serialization - */ - @Test - public void testSerialization() { - final GraphDocument doc = new GraphDocument(); - - test(doc); - - final Group group1 = new Group(doc); - doc.addElement(group1); - test(doc); - - final Group group2 = new Group(doc); - doc.addElement(group2); - test(doc); - - final InputGraph graph = new InputGraph(""); - group1.addElement(graph); - test(doc); - - graph.addNode(new InputNode(0)); - test(doc); - - graph.addNode(new InputNode(1)); - test(doc); - - graph.addNode(new InputNode(2)); - test(doc); - - graph.addNode(new InputNode(3)); - test(doc); - - graph.addEdge(new InputEdge((char)0, (char)0, 0, 1)); - test(doc); - - graph.addEdge(new InputEdge((char)1, (char)1, 0, 1)); - test(doc); - - graph.addEdge(new InputEdge((char)0, (char)0, 1, 2)); - test(doc); - - graph.addEdge(new InputEdge((char)0, (char)0, 2, 3)); - test(doc); - - group1.setMethod(new InputMethod(group1, "testMethod", "tM", 1)); - test(doc); - - final InputBlock b1 = graph.addBlock("1"); - b1.addNode(0); - b1.addNode(1); - - final InputBlock b2 = graph.addBlock("2"); - b2.addNode(2); - b2.addNode(3); - test(doc); - - final GraphDocument document2 = new GraphDocument(); - doc.addGraphDocument(document2); - test(doc); - assertTrue(doc.getElements().size() == 2); - - final Group group3 = new Group(document2); - document2.addElement(group3); - doc.addGraphDocument(document2); - assertTrue(doc.getElements().size() == 3); - assertTrue(document2.getElements().size() == 0); - - doc.clear(); - test(doc); - Util.assertGraphDocumentEquals(doc, new GraphDocument()); - } - - @Test - public void testSimpleExport() { - GraphDocument document = new GraphDocument(); - Group g = new Group(document); - document.addElement(g); - - InputGraph graph = new InputGraph("TestGraph"); - g.addElement(graph); - graph.getProperties().setProperty("testName", "testValue"); - - InputNode n1 = new InputNode(0); - InputNode n2 = new InputNode(1); - InputEdge e1 = new InputEdge((char)0, 0, 1); - InputEdge e2 = new InputEdge((char)1, 0, 1); - graph.addNode(n1); - graph.addNode(n2); - graph.addEdge(e1); - graph.addEdge(e2); - - test(document); - } - - @Test - public void testComplexExport() { - - GraphDocument document = new GraphDocument(); - Group g = new Group(document); - document.addElement(g); - - InputGraph graph = new InputGraph("TestGraph"); - g.addElement(graph); - graph.getProperties().setProperty("testName", "testValue"); - - InputNode n1 = new InputNode(0); - InputNode n2 = new InputNode(1); - InputEdge e1 = new InputEdge((char)0, 0, 0); - InputEdge e2 = new InputEdge((char)1, 1, 1); - graph.addNode(n1); - graph.addNode(n2); - graph.addEdge(e1); - graph.addEdge(e2); - - InputGraph graph2 = new InputGraph("TestGraph2"); - g.addElement(graph2); - graph2.addNode(n1); - InputNode n3 = new InputNode(2); - graph2.addNode(n3); - InputEdge e3 = new InputEdge((char)0, 0, 2); - graph2.addEdge(e3); - - test(document); - } - - - /** - * Test of parse method, of class Parser. - */ - @Test - public void testParse() { - testBoth(new GraphDocument(), ""); - } - -} \ No newline at end of file diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Difference/build.xml --- a/visualizer/Difference/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project com.sun.hotspot.igv.difference. - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Difference/manifest.mf --- a/visualizer/Difference/manifest.mf Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.sun.hotspot.igv.difference -OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/difference/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Difference/nbproject/build-impl.xml --- a/visualizer/Difference/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Difference/nbproject/genfiles.properties --- a/visualizer/Difference/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -build.xml.data.CRC32=1657ecfe -build.xml.script.CRC32=03909051 -build.xml.stylesheet.CRC32=79c3b980 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=1657ecfe -nbproject/build-impl.xml.script.CRC32=2208e770 -nbproject/build-impl.xml.stylesheet.CRC32=deb65f65 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Difference/nbproject/platform.properties --- a/visualizer/Difference/nbproject/platform.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -# Deprecated since 5.0u1; for compatibility with 5.0: -disabled.clusters=\ - apisupport1,\ - harness,\ - ide8,\ - java1,\ - nb6.0,\ - profiler2 -disabled.modules=\ - org.netbeans.core.execution,\ - org.netbeans.core.multiview,\ - org.netbeans.core.output2,\ - org.netbeans.modules.applemenu,\ - org.netbeans.modules.autoupdate.services,\ - org.netbeans.modules.autoupdate.ui,\ - org.netbeans.modules.core.kit,\ - org.netbeans.modules.favorites,\ - org.netbeans.modules.javahelp,\ - org.netbeans.modules.masterfs,\ - org.netbeans.modules.options.keymap,\ - org.netbeans.modules.sendopts,\ - org.netbeans.modules.templates,\ - org.openide.compat,\ - org.openide.execution,\ - org.openide.util.enumerations -enabled.clusters=\ - platform7 -nbjdk.active=JDK_1.6 -nbplatform.active=default diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Difference/nbproject/project.properties --- a/visualizer/Difference/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -javac.source=1.7 -javac.compilerargs=-Xlint -Xlint:-serial diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Difference/nbproject/project.xml --- a/visualizer/Difference/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - com.sun.hotspot.igv.difference - - - - com.sun.hotspot.igv.data - - - - 1.0 - - - - org.openide.util.lookup - - - - 8.6.1 - - - - - com.sun.hotspot.igv.difference - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Difference/nbproject/suite.properties --- a/visualizer/Difference/nbproject/suite.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -suite.dir=${basedir}/.. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Difference/src/com/sun/hotspot/igv/difference/Bundle.properties --- a/visualizer/Difference/src/com/sun/hotspot/igv/difference/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -OpenIDE-Module-Name=Difference diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java --- a/visualizer/Difference/src/com/sun/hotspot/igv/difference/Difference.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,381 +0,0 @@ -/* - * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 com.sun.hotspot.igv.difference; - -import com.sun.hotspot.igv.data.Properties; -import com.sun.hotspot.igv.data.*; -import com.sun.hotspot.igv.data.services.Scheduler; -import java.util.*; -import org.openide.util.Lookup; - -/** - * - * @author Thomas Wuerthinger - */ -public class Difference { - - public static final String PROPERTY_STATE = "state"; - public static final String VALUE_NEW = "new"; - public static final String VALUE_CHANGED = "changed"; - public static final String VALUE_SAME = "same"; - public static final String VALUE_DELETED = "deleted"; - public static final String OLD_PREFIX = "OLD_"; - public static final String MAIN_PROPERTY = "name"; - public static final double LIMIT = 100.0; - public static final String[] IGNORE_PROPERTIES = new String[]{"idx", "debug_idx"}; - - public static InputGraph createDiffGraph(InputGraph a, InputGraph b) { - if (a.getGroup() == b.getGroup()) { - return createDiffSameGroup(a, b); - } else { - return createDiff(a, b); - } - } - - private static InputGraph createDiffSameGroup(InputGraph a, InputGraph b) { - Map keyMapB = new HashMap<>(b.getNodes().size()); - for (InputNode n : b.getNodes()) { - Integer key = n.getId(); - assert !keyMapB.containsKey(key); - keyMapB.put(key, n); - } - - Set pairs = new HashSet<>(); - - for (InputNode n : a.getNodes()) { - Integer key = n.getId(); - - - if (keyMapB.containsKey(key)) { - InputNode nB = keyMapB.get(key); - pairs.add(new NodePair(n, nB)); - } - } - - return createDiff(a, b, pairs); - } - - private static void ensureScheduled(InputGraph a) { - if (a.getBlocks().isEmpty()) { - Scheduler s = Lookup.getDefault().lookup(Scheduler.class); - a.clearBlocks(); - s.schedule(a); - a.ensureNodesInBlocks(); - } - } - - private static InputGraph createDiff(InputGraph a, InputGraph b, Set pairs) { - ensureScheduled(a); - ensureScheduled(b); - - Group g = new Group(null); - g.setMethod(a.getGroup().getMethod()); - if (a.getGroup() == b.getGroup()) { - g.getProperties().add(a.getGroup().getProperties()); - } else { - // copy properties that have the same value in both groups - Properties bps = b.getGroup().getProperties(); - for (Property p : a.getGroup().getProperties()) { - String value = p.getValue(); - if (value != null && value.equals(bps.get(p.getName()))) { - g.getProperties().setProperty(p.getName(), value); - } - } - } - g.getProperties().setProperty("name", "Difference"); - InputGraph graph = new InputGraph(a.getName() + ", " + b.getName()); - g.addElement(graph); - - Map blocksMap = new HashMap<>(); - for (InputBlock blk : a.getBlocks()) { - InputBlock diffblk = graph.addBlock(blk.getName()); - blocksMap.put(blk, diffblk); - } - for (InputBlock blk : b.getBlocks()) { - InputBlock diffblk = graph.getBlock(blk.getName()); - if (diffblk == null) { - diffblk = graph.addBlock(blk.getName()); - } - blocksMap.put(blk, diffblk); - } - - // Difference between block edges - Set> aEdges = new HashSet<>(); - for (InputBlockEdge edge : a.getBlockEdges()) { - aEdges.add(new Pair<>(edge.getFrom().getName(), edge.getTo().getName())); - } - for (InputBlockEdge bEdge : b.getBlockEdges()) { - InputBlock from = bEdge.getFrom(); - InputBlock to = bEdge.getTo(); - Pair pair = new Pair<>(from.getName(), to.getName()); - if (aEdges.contains(pair)) { - // same - graph.addBlockEdge(blocksMap.get(from), blocksMap.get(to)); - aEdges.remove(pair); - } else { - // added - InputBlockEdge edge = graph.addBlockEdge(blocksMap.get(from), blocksMap.get(to)); - edge.setState(InputBlockEdge.State.NEW); - } - } - for (Pair deleted : aEdges) { - // removed - InputBlock from = graph.getBlock(deleted.getLeft()); - InputBlock to = graph.getBlock(deleted.getRight()); - InputBlockEdge edge = graph.addBlockEdge(from, to); - edge.setState(InputBlockEdge.State.DELETED); - } - - Set nodesA = new HashSet<>(a.getNodes()); - Set nodesB = new HashSet<>(b.getNodes()); - - Map inputNodeMap = new HashMap<>(pairs.size()); - for (NodePair p : pairs) { - InputNode n = p.getLeft(); - assert nodesA.contains(n); - InputNode nB = p.getRight(); - assert nodesB.contains(nB); - - nodesA.remove(n); - nodesB.remove(nB); - InputNode n2 = new InputNode(n); - inputNodeMap.put(n, n2); - inputNodeMap.put(nB, n2); - graph.addNode(n2); - InputBlock block = blocksMap.get(a.getBlock(n)); - block.addNode(n2.getId()); - markAsChanged(n2, n, nB); - } - - for (InputNode n : nodesA) { - InputNode n2 = new InputNode(n); - graph.addNode(n2); - InputBlock block = blocksMap.get(a.getBlock(n)); - block.addNode(n2.getId()); - markAsDeleted(n2); - inputNodeMap.put(n, n2); - } - - int curIndex = 0; - for (InputNode n : nodesB) { - InputNode n2 = new InputNode(n); - - // Find new ID for node of b, does not change the id property - while (graph.getNode(curIndex) != null) { - curIndex++; - } - - n2.setId(curIndex); - graph.addNode(n2); - InputBlock block = blocksMap.get(b.getBlock(n)); - block.addNode(n2.getId()); - markAsNew(n2); - inputNodeMap.put(n, n2); - } - - Collection edgesA = a.getEdges(); - Collection edgesB = b.getEdges(); - - Set newEdges = new HashSet<>(); - - for (InputEdge e : edgesA) { - int from = e.getFrom(); - int to = e.getTo(); - InputNode nodeFrom = inputNodeMap.get(a.getNode(from)); - InputNode nodeTo = inputNodeMap.get(a.getNode(to)); - char fromIndex = e.getFromIndex(); - char toIndex = e.getToIndex(); - - InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId()); - if (!newEdges.contains(newEdge)) { - markAsDeleted(newEdge); - newEdges.add(newEdge); - graph.addEdge(newEdge); - } - } - - for (InputEdge e : edgesB) { - int from = e.getFrom(); - int to = e.getTo(); - InputNode nodeFrom = inputNodeMap.get(b.getNode(from)); - InputNode nodeTo = inputNodeMap.get(b.getNode(to)); - char fromIndex = e.getFromIndex(); - char toIndex = e.getToIndex(); - - InputEdge newEdge = new InputEdge(fromIndex, toIndex, nodeFrom.getId(), nodeTo.getId()); - if (!newEdges.contains(newEdge)) { - markAsNew(newEdge); - newEdges.add(newEdge); - graph.addEdge(newEdge); - } else { - newEdges.remove(newEdge); - graph.removeEdge(newEdge); - markAsSame(newEdge); - newEdges.add(newEdge); - graph.addEdge(newEdge); - } - } - - return graph; - } - - private static class NodePair extends Pair { - - - public NodePair(InputNode n1, InputNode n2) { - super(n1, n2); - } - - public double getValue() { - - double result = 0.0; - for (Property p : getLeft().getProperties()) { - double faktor = 1.0; - for (String forbidden : IGNORE_PROPERTIES) { - if (p.getName().equals(forbidden)) { - faktor = 0.1; - break; - } - } - String p2 = getRight().getProperties().get(p.getName()); - result += evaluate(p.getValue(), p2) * faktor; - } - - return result; - } - - private double evaluate(String p, String p2) { - if (p2 == null) { - return 1.0; - } - if (p.equals(p2)) { - return 0.0; - } else { - return (double) (Math.abs(p.length() - p2.length())) / p.length() + 0.5; - } - } - } - - private static InputGraph createDiff(InputGraph a, InputGraph b) { - - Set matched = new HashSet<>(); - - Set pairs = new HashSet<>(); - for (InputNode n : a.getNodes()) { - String s = n.getProperties().get(MAIN_PROPERTY); - if (s == null) { - s = ""; - } - for (InputNode n2 : b.getNodes()) { - String s2 = n2.getProperties().get(MAIN_PROPERTY); - if (s2 == null) { - s2 = ""; - } - - if (s.equals(s2)) { - NodePair p = new NodePair(n, n2); - pairs.add(p); - } - } - } - - Set selectedPairs = new HashSet<>(); - while (pairs.size() > 0) { - - double min = Double.MAX_VALUE; - NodePair minPair = null; - for (NodePair p : pairs) { - double cur = p.getValue(); - if (cur < min) { - minPair = p; - min = cur; - } - } - - if (min > LIMIT) { - break; - } else { - selectedPairs.add(minPair); - - Set toRemove = new HashSet<>(); - for (NodePair p : pairs) { - if (p.getLeft() == minPair.getLeft() || p.getRight() == minPair.getRight()) { - toRemove.add(p); - } - } - pairs.removeAll(toRemove); - } - } - - return createDiff(a, b, selectedPairs); - } - - private static void markAsNew(InputEdge e) { - e.setState(InputEdge.State.NEW); - } - - private static void markAsDeleted(InputEdge e) { - e.setState(InputEdge.State.DELETED); - - } - - private static void markAsSame(InputEdge e) { - e.setState(InputEdge.State.SAME); - } - - private static void markAsChanged(InputNode n, InputNode firstNode, InputNode otherNode) { - - boolean difference = false; - for (Property p : otherNode.getProperties()) { - String s = firstNode.getProperties().get(p.getName()); - if (!p.getValue().equals(s)) { - difference = true; - n.getProperties().setProperty(OLD_PREFIX + p.getName(), p.getValue()); - } - } - - for (Property p : firstNode.getProperties()) { - String s = otherNode.getProperties().get(p.getName()); - if (s == null && p.getValue().length() > 0) { - difference = true; - n.getProperties().setProperty(OLD_PREFIX + p.getName(), ""); - } - } - - if (difference) { - n.getProperties().setProperty(PROPERTY_STATE, VALUE_CHANGED); - } else { - n.getProperties().setProperty(PROPERTY_STATE, VALUE_SAME); - } - } - - private static void markAsDeleted(InputNode n) { - n.getProperties().setProperty(PROPERTY_STATE, VALUE_DELETED); - } - - private static void markAsNew(InputNode n) { - n.getProperties().setProperty(PROPERTY_STATE, VALUE_NEW); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Draw2DLibrary/build.xml --- a/visualizer/Draw2DLibrary/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project org.eclipse.draw2d. - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Draw2DLibrary/manifest.mf --- a/visualizer/Draw2DLibrary/manifest.mf Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: org.eclipse.draw2d -OpenIDE-Module-Localizing-Bundle: org/eclipse/draw2d/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Draw2DLibrary/nbproject/build-impl.xml --- a/visualizer/Draw2DLibrary/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ - - - - - - - - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Draw2DLibrary/nbproject/genfiles.properties --- a/visualizer/Draw2DLibrary/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -build.xml.data.CRC32=36988202 -build.xml.script.CRC32=0429cbcb -build.xml.stylesheet.CRC32=a56c6a5b@2.47.1 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=36988202 -nbproject/build-impl.xml.script.CRC32=92856d71 -nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Draw2DLibrary/nbproject/platform.properties --- a/visualizer/Draw2DLibrary/nbproject/platform.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,204 +0,0 @@ -cluster.path=\ - ${nbplatform.active.dir}/ide:\ - ${nbplatform.active.dir}/platform -disabled.modules=\ - com.jcraft.jsch,\ - com.jcraft.jzlib,\ - org.apache.commons.codec,\ - org.apache.commons.httpclient,\ - org.apache.commons.io,\ - org.apache.commons.lang,\ - org.apache.commons.logging,\ - org.apache.ws.commons.util,\ - org.apache.xml.resolver,\ - org.apache.xmlrpc,\ - org.eclipse.core.contenttype,\ - org.eclipse.core.jobs,\ - org.eclipse.core.net,\ - org.eclipse.core.runtime,\ - org.eclipse.core.runtime.compatibility.auth,\ - org.eclipse.equinox.app,\ - org.eclipse.equinox.common,\ - org.eclipse.equinox.preferences,\ - org.eclipse.equinox.registry,\ - org.eclipse.equinox.security,\ - org.eclipse.jgit,\ - org.eclipse.mylyn.bugzilla.core,\ - org.eclipse.mylyn.commons.core,\ - org.eclipse.mylyn.commons.net,\ - org.eclipse.mylyn.commons.xmlrpc,\ - org.eclipse.mylyn.tasks.core,\ - org.mozilla.rhino.patched,\ - org.netbeans.api.debugger,\ - org.netbeans.api.java.classpath,\ - org.netbeans.api.xml,\ - org.netbeans.core.browser,\ - org.netbeans.core.execution,\ - org.netbeans.core.ide,\ - org.netbeans.core.io.ui,\ - org.netbeans.core.multiview,\ - org.netbeans.core.nativeaccess,\ - org.netbeans.core.osgi,\ - org.netbeans.lib.cvsclient,\ - org.netbeans.lib.terminalemulator,\ - org.netbeans.libs.antlr3.runtime,\ - org.netbeans.libs.bytelist,\ - org.netbeans.libs.commons_net,\ - org.netbeans.libs.freemarker,\ - org.netbeans.libs.git,\ - org.netbeans.libs.ini4j,\ - org.netbeans.libs.jaxb,\ - org.netbeans.libs.jsr223,\ - org.netbeans.libs.junit4,\ - org.netbeans.libs.jvyamlb,\ - org.netbeans.libs.lucene,\ - org.netbeans.libs.smack,\ - org.netbeans.libs.svnClientAdapter,\ - org.netbeans.libs.svnClientAdapter.javahl,\ - org.netbeans.libs.svnClientAdapter.svnkit,\ - org.netbeans.libs.swingx,\ - org.netbeans.libs.xerces,\ - org.netbeans.modules.autoupdate.services,\ - org.netbeans.modules.autoupdate.ui,\ - org.netbeans.modules.bugtracking,\ - org.netbeans.modules.bugtracking.bridge,\ - org.netbeans.modules.bugzilla,\ - org.netbeans.modules.core.kit,\ - org.netbeans.modules.csl.api,\ - org.netbeans.modules.css.editor,\ - org.netbeans.modules.css.lib,\ - org.netbeans.modules.css.visual,\ - org.netbeans.modules.db,\ - org.netbeans.modules.db.core,\ - org.netbeans.modules.db.dataview,\ - org.netbeans.modules.db.drivers,\ - org.netbeans.modules.db.kit,\ - org.netbeans.modules.db.metadata.model,\ - org.netbeans.modules.db.mysql,\ - org.netbeans.modules.db.sql.editor,\ - org.netbeans.modules.db.sql.visualeditor,\ - org.netbeans.modules.dbapi,\ - org.netbeans.modules.defaults,\ - org.netbeans.modules.derby,\ - org.netbeans.modules.dlight.nativeexecution,\ - org.netbeans.modules.dlight.terminal,\ - org.netbeans.modules.editor.bookmarks,\ - org.netbeans.modules.editor.bracesmatching,\ - org.netbeans.modules.editor.codetemplates,\ - org.netbeans.modules.editor.completion,\ - org.netbeans.modules.editor.guards,\ - org.netbeans.modules.editor.indent.project,\ - org.netbeans.modules.editor.kit,\ - org.netbeans.modules.editor.macros,\ - org.netbeans.modules.editor.structure,\ - org.netbeans.modules.extbrowser,\ - org.netbeans.modules.extexecution,\ - org.netbeans.modules.extexecution.destroy,\ - org.netbeans.modules.favorites,\ - org.netbeans.modules.git,\ - org.netbeans.modules.glassfish.common,\ - org.netbeans.modules.gototest,\ - org.netbeans.modules.gsf.codecoverage,\ - org.netbeans.modules.gsf.testrunner,\ - org.netbeans.modules.html,\ - org.netbeans.modules.html.editor,\ - org.netbeans.modules.html.editor.lib,\ - org.netbeans.modules.html.lexer,\ - org.netbeans.modules.html.parser,\ - org.netbeans.modules.html.validation,\ - org.netbeans.modules.httpserver,\ - org.netbeans.modules.hudson,\ - org.netbeans.modules.hudson.git,\ - org.netbeans.modules.hudson.mercurial,\ - org.netbeans.modules.hudson.subversion,\ - org.netbeans.modules.hudson.tasklist,\ - org.netbeans.modules.ide.kit,\ - org.netbeans.modules.image,\ - org.netbeans.modules.javascript.editing,\ - org.netbeans.modules.javascript.hints,\ - org.netbeans.modules.javascript.kit,\ - org.netbeans.modules.javascript.refactoring,\ - org.netbeans.modules.jellytools.ide,\ - org.netbeans.modules.jumpto,\ - org.netbeans.modules.keyring.impl,\ - org.netbeans.modules.languages,\ - org.netbeans.modules.languages.diff,\ - org.netbeans.modules.languages.manifest,\ - org.netbeans.modules.languages.yaml,\ - org.netbeans.modules.lexer.nbbridge,\ - org.netbeans.modules.localhistory,\ - org.netbeans.modules.mercurial,\ - org.netbeans.modules.netbinox,\ - org.netbeans.modules.parsing.api,\ - org.netbeans.modules.parsing.lucene,\ - org.netbeans.modules.print.editor,\ - org.netbeans.modules.project.ant,\ - org.netbeans.modules.project.libraries,\ - org.netbeans.modules.projectui,\ - org.netbeans.modules.projectui.buildmenu,\ - org.netbeans.modules.projectuiapi,\ - org.netbeans.modules.properties,\ - org.netbeans.modules.properties.syntax,\ - org.netbeans.modules.refactoring.api,\ - org.netbeans.modules.schema2beans,\ - org.netbeans.modules.server,\ - org.netbeans.modules.servletapi,\ - org.netbeans.modules.spellchecker,\ - org.netbeans.modules.spellchecker.apimodule,\ - org.netbeans.modules.spellchecker.bindings.htmlxml,\ - org.netbeans.modules.spellchecker.bindings.properties,\ - org.netbeans.modules.spellchecker.dictionary_en,\ - org.netbeans.modules.spellchecker.kit,\ - org.netbeans.modules.spi.actions,\ - org.netbeans.modules.subversion,\ - org.netbeans.modules.swing.validation,\ - org.netbeans.modules.target.iterator,\ - org.netbeans.modules.tasklist.kit,\ - org.netbeans.modules.tasklist.projectint,\ - org.netbeans.modules.tasklist.todo,\ - org.netbeans.modules.tasklist.ui,\ - org.netbeans.modules.terminal,\ - org.netbeans.modules.usersguide,\ - org.netbeans.modules.utilities,\ - org.netbeans.modules.utilities.project,\ - org.netbeans.modules.versioning,\ - org.netbeans.modules.versioning.indexingbridge,\ - org.netbeans.modules.versioning.system.cvss.installer,\ - org.netbeans.modules.versioning.util,\ - org.netbeans.modules.web.client.tools.api,\ - org.netbeans.modules.web.common,\ - org.netbeans.modules.web.indent,\ - org.netbeans.modules.xml,\ - org.netbeans.modules.xml.axi,\ - org.netbeans.modules.xml.catalog,\ - org.netbeans.modules.xml.core,\ - org.netbeans.modules.xml.jaxb.api,\ - org.netbeans.modules.xml.lexer,\ - org.netbeans.modules.xml.multiview,\ - org.netbeans.modules.xml.retriever,\ - org.netbeans.modules.xml.schema.completion,\ - org.netbeans.modules.xml.schema.model,\ - org.netbeans.modules.xml.tax,\ - org.netbeans.modules.xml.text,\ - org.netbeans.modules.xml.tools,\ - org.netbeans.modules.xml.wsdl.model,\ - org.netbeans.modules.xml.xam,\ - org.netbeans.modules.xml.xdm,\ - org.netbeans.modules.xsl,\ - org.netbeans.spi.debugger.ui,\ - org.netbeans.spi.editor.hints,\ - org.netbeans.spi.navigator,\ - org.netbeans.spi.palette,\ - org.netbeans.spi.tasklist,\ - org.netbeans.spi.viewmodel,\ - org.netbeans.swing.dirchooser,\ - org.openide.compat,\ - org.openide.execution,\ - org.openide.options,\ - org.openide.util.enumerations -## Not disabled because of NetBeans bug 206347: -## Applications not using OSGi don't start on NbP 7.1 -# org.netbeans.core.netigso,\ -# org.netbeans.libs.felix,\ -# org.netbeans.libs.osgi,\ -nbplatform.active=default diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Draw2DLibrary/nbproject/project.properties --- a/visualizer/Draw2DLibrary/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -is.autoload=true diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Draw2DLibrary/nbproject/project.xml --- a/visualizer/Draw2DLibrary/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - org.eclipse.draw2d - - - - org.eclipse.draw2d - org.eclipse.draw2d.geometry - org.eclipse.draw2d.graph - org.eclipse.draw2d.internal - org.eclipse.draw2d.internal.graph - org.eclipse.draw2d.parts - org.eclipse.draw2d.text - org.eclipse.draw2d.widgets - - - ext/org.eclipse.draw2d_3.1.0.jar - release/modules/ext/org.eclipse.draw2d_3.1.0.jar - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Draw2DLibrary/nbproject/suite.properties --- a/visualizer/Draw2DLibrary/nbproject/suite.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -suite.dir=${basedir}/.. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Draw2DLibrary/release/modules/ext/org.eclipse.draw2d_3.1.0.jar Binary file visualizer/Draw2DLibrary/release/modules/ext/org.eclipse.draw2d_3.1.0.jar has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Draw2DLibrary/src/org/eclipse/draw2d/Bundle.properties --- a/visualizer/Draw2DLibrary/src/org/eclipse/draw2d/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -OpenIDE-Module-Name=Draw2DLibrary diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Editor/build.xml --- a/visualizer/Editor/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project com.oracle.graal.visualizer.editor. - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Editor/manifest.mf --- a/visualizer/Editor/manifest.mf Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.oracle.graal.visualizer.editor -OpenIDE-Module-Layer: com/oracle/graal/visualizer/editor/layer.xml -OpenIDE-Module-Localizing-Bundle: com/oracle/graal/visualizer/editor/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Editor/nbproject/build-impl.xml --- a/visualizer/Editor/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ - - - - - - - - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Editor/nbproject/genfiles.properties --- a/visualizer/Editor/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -build.xml.data.CRC32=5dcda8e3 -build.xml.script.CRC32=98c4f3b3 -build.xml.stylesheet.CRC32=a56c6a5b@2.47.1 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=5dcda8e3 -nbproject/build-impl.xml.script.CRC32=6243c7e2 -nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Editor/nbproject/project.properties --- a/visualizer/Editor/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -javac.source=1.7 -javac.compilerargs=-Xlint -Xlint:-serial diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Editor/nbproject/project.xml --- a/visualizer/Editor/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,136 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - com.oracle.graal.visualizer.editor - - - - com.sun.hotspot.igv.data - - - - 1.0 - - - - com.sun.hotspot.igv.difference - - - - 1.0 - - - - com.sun.hotspot.igv.filter - - - - 1.0 - - - - com.sun.hotspot.igv.graph - - - - 1.0 - - - - com.sun.hotspot.igv.settings - - - - 1.0 - - - - com.sun.hotspot.igv.util - - - - 1.0 - - - - org.netbeans.spi.quicksearch - - - - 1.12.1 - - - - org.openide.actions - - - - 6.24.1 - - - - org.openide.awt - - - - 7.39.1 - - - - org.openide.dialogs - - - - 7.23.1 - - - - org.openide.filesystems - - - - 7.53.2 - - - - org.openide.loaders - - - - 7.32.1 - - - - org.openide.util - - - - 8.19.1 - - - - org.openide.util.lookup - - - - 8.11.1 - - - - org.openide.windows - - - - 6.48.1 - - - - - com.oracle.graal.visualizer.editor - com.oracle.graal.visualizer.editor.actions - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Editor/nbproject/suite.properties --- a/visualizer/Editor/nbproject/suite.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -suite.dir=${basedir}/.. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Editor/src/META-INF/services/com.sun.hotspot.igv.data.services.GraphViewer --- a/visualizer/Editor/src/META-INF/services/com.sun.hotspot.igv.data.services.GraphViewer Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -com.oracle.graal.visualizer.editor.GraphViewerImplementation diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Editor/src/com/oracle/graal/visualizer/editor/Bundle.properties --- a/visualizer/Editor/src/com/oracle/graal/visualizer/editor/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -OpenIDE-Module-Name=Editor -CTL_EditorTopComponent=Compilation -HINT_EditorTopComponent=Shows the snapshots of a single compilation. \ No newline at end of file diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Editor/src/com/oracle/graal/visualizer/editor/CompilationViewer.java --- a/visualizer/Editor/src/com/oracle/graal/visualizer/editor/CompilationViewer.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.editor; - -import com.sun.hotspot.igv.graph.Figure; -import java.awt.Component; -import java.awt.Graphics2D; -import java.util.Collection; -import org.openide.awt.UndoRedo; -import org.openide.util.Lookup; - -/** - * - * @author Thomas Wuerthinger - */ -public interface CompilationViewer { - - public Lookup getLookup(); - - public Component getComponent(); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Editor/src/com/oracle/graal/visualizer/editor/CompilationViewerFactory.java --- a/visualizer/Editor/src/com/oracle/graal/visualizer/editor/CompilationViewerFactory.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.oracle.graal.visualizer.editor; - -import com.sun.hotspot.igv.data.InputGraph; - -public interface CompilationViewerFactory { - CompilationViewer createViewer(InputGraph firstGraph, InputGraph secondGraph); - String getName(); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Editor/src/com/oracle/graal/visualizer/editor/DiagramViewModel.java --- a/visualizer/Editor/src/com/oracle/graal/visualizer/editor/DiagramViewModel.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,289 +0,0 @@ -/* - * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 com.oracle.graal.visualizer.editor; - -import com.sun.hotspot.igv.data.*; -import com.sun.hotspot.igv.difference.Difference; -import com.sun.hotspot.igv.filter.CustomFilter; -import com.sun.hotspot.igv.filter.FilterChain; -import com.sun.hotspot.igv.graph.Diagram; -import com.sun.hotspot.igv.graph.Figure; -import com.sun.hotspot.igv.settings.Settings; -import java.util.*; - -public class DiagramViewModel { - - private Set hiddenNodes; - private Set onScreenNodes; - private Set selectedNodes; - private FilterChain filterChain; - private FilterChain sequenceFilterChain; - private Diagram diagram; - private InputGraph inputGraph; - private ChangedEvent diagramChangedEvent; - private ChangedEvent viewChangedEvent; - private ChangedEvent hiddenNodesChangedEvent; - private ChangedEvent viewPropertiesChangedEvent; - private boolean showNodeHull; - private final InputGraph secondGraph; - private final InputGraph firstGraph; - private ChangedListener filterChainChangedListener = new ChangedListener() { - - @Override - public void changed(FilterChain source) { - diagramChanged(); - } - }; - - public boolean getShowNodeHull() { - return showNodeHull; - } - - public void setShowNodeHull(boolean b) { - showNodeHull = b; - viewPropertiesChangedEvent.fire(); - } - - public DiagramViewModel(InputGraph firstGraph, InputGraph secondGraph, Group g, FilterChain filterChain, FilterChain sequenceFilterChain) { - - this.firstGraph = firstGraph; - this.secondGraph = secondGraph; - this.showNodeHull = true; - assert filterChain != null; - this.filterChain = filterChain; - assert sequenceFilterChain != null; - this.sequenceFilterChain = sequenceFilterChain; - hiddenNodes = new HashSet<>(); - onScreenNodes = new HashSet<>(); - selectedNodes = new HashSet<>(); - diagramChangedEvent = new ChangedEvent<>(this); - viewChangedEvent = new ChangedEvent<>(this); - hiddenNodesChangedEvent = new ChangedEvent<>(this); - viewPropertiesChangedEvent = new ChangedEvent<>(this); - - filterChain.getChangedEvent().addListener(filterChainChangedListener); - sequenceFilterChain.getChangedEvent().addListener(filterChainChangedListener); - } - - public ChangedEvent getDiagramChangedEvent() { - return diagramChangedEvent; - } - - public ChangedEvent getViewChangedEvent() { - return viewChangedEvent; - } - - public ChangedEvent getHiddenNodesChangedEvent() { - return hiddenNodesChangedEvent; - } - - public ChangedEvent getViewPropertiesChangedEvent() { - return viewPropertiesChangedEvent; - } - - public Set getSelectedNodes() { - return selectedNodes; - } - - public Set getHiddenNodes() { - return hiddenNodes; - } - - public Set getOnScreenNodes() { - return onScreenNodes; - } - - public void setSelectedNodes(Set nodes) { - this.selectedNodes = nodes; - /* List colors = new ArrayList<>(); - for (int i = 0; i < group.getGraphs().size(); ++i) { - colors.add(Color.black); - } - if (nodes.size() >= 1) { - for (Integer id : nodes) { - if (id < 0) { - id = -id; - } - InputNode last = null; - int index = 0; - for (InputGraph g : group.getGraphs()) { - Color curColor = colors.get(index); - InputNode cur = g.getNode(id); - if (cur != null) { - if (last == null) { - curColor = Color.green; - } else { - if (last.equals(cur)) { - if (curColor == Color.black) { - curColor = Color.white; - } - } else { - if (curColor != Color.green) { - curColor = Color.orange; - } - } - } - } - last = cur; - colors.set(index, curColor); - index++; - } - } - } - compilationViewModel.setColors(colors);*/ - // TODO: Add colorization. - viewChangedEvent.fire(); - } - - public void showNot(final Set nodes) { - System.out.println("Shownot called with " + nodes); - setHiddenNodes(nodes); - } - - public void showFigures(Collection

f) { - HashSet newHiddenNodes = new HashSet<>(getHiddenNodes()); - for (Figure fig : f) { - newHiddenNodes.removeAll(fig.getSource().getSourceNodesAsSet()); - } - setHiddenNodes(newHiddenNodes); - } - - public Set
getSelectedFigures() { - Set
result = new HashSet<>(); - for (Figure f : diagram.getFigures()) { - for (InputNode node : f.getSource().getSourceNodes()) { - if (getSelectedNodes().contains(node.getId())) { - result.add(f); - } - } - } - return result; - } - - public void showAll(final Collection
f) { - showFigures(f); - } - - public void showOnly(final Set nodes) { - final HashSet allNodes = new HashSet<>(getGraphToView().getGroup().getAllNodes()); - allNodes.removeAll(nodes); - setHiddenNodes(allNodes); - } - - public void setHiddenNodes(Set nodes) { - this.hiddenNodes = nodes; - hiddenNodesChangedEvent.fire(); - } - - public void setOnScreenNodes(Set onScreenNodes) { - this.onScreenNodes = onScreenNodes; - viewChangedEvent.fire(); - } - - public FilterChain getSequenceFilterChain() { - return filterChain; - } - - public void setSequenceFilterChain(FilterChain chain) { - assert chain != null : "sequenceFilterChain must never be null"; - sequenceFilterChain.getChangedEvent().removeListener(filterChainChangedListener); - sequenceFilterChain = chain; - sequenceFilterChain.getChangedEvent().addListener(filterChainChangedListener); - diagramChanged(); - } - - private void diagramChanged() { - // clear diagram - diagram = null; - getDiagramChangedEvent().fire(); - - } - - public FilterChain getFilterChain() { - return filterChain; - } - - public void setFilterChain(FilterChain chain) { - assert chain != null : "filterChain must never be null"; - filterChain.getChangedEvent().removeListener(filterChainChangedListener); - filterChain = chain; - filterChain.getChangedEvent().addListener(filterChainChangedListener); - diagramChanged(); - } - - private static List calculateStringList(Group g) { - List result = new ArrayList<>(); - for (InputGraph graph : g.getGraphs()) { - result.add(graph.getName()); - } - return result; - } - - public InputGraph getFirstGraph() { - return firstGraph; - } - - public InputGraph getSecondGraph() { - return secondGraph; - } - - public Diagram getDiagramToView() { - - if (diagram == null) { - diagram = Diagram.createDiagram(getGraphToView(), Settings.get().get(Settings.NODE_TEXT, Settings.NODE_TEXT_DEFAULT)); - getFilterChain().apply(diagram, getSequenceFilterChain()); - if (getFirstGraph() != getSecondGraph()) { - CustomFilter f = new CustomFilter( - "difference", "colorize('state', 'same', white);" - + "colorize('state', 'changed', orange);" - + "colorize('state', 'new', green);" - + "colorize('state', 'deleted', red);"); - f.apply(diagram); - } - } - - return diagram; - } - - public InputGraph getGraphToView() { - if (inputGraph == null) { - if (getFirstGraph() != getSecondGraph()) { - inputGraph = Difference.createDiffGraph(getFirstGraph(), getSecondGraph()); - } else { - inputGraph = getFirstGraph(); - } - } - - return inputGraph; - } - - void setSelectedFigures(List
list) { - Set newSelectedNodes = new HashSet<>(); - for (Figure f : list) { - newSelectedNodes.addAll(f.getSource().getSourceNodesAsSet()); - } - this.setSelectedNodes(newSelectedNodes); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Editor/src/com/oracle/graal/visualizer/editor/EditorTopComponent.form --- a/visualizer/Editor/src/com/oracle/graal/visualizer/editor/EditorTopComponent.form Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Editor/src/com/oracle/graal/visualizer/editor/EditorTopComponent.java --- a/visualizer/Editor/src/com/oracle/graal/visualizer/editor/EditorTopComponent.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,291 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.oracle.graal.visualizer.editor; - -import com.oracle.graal.visualizer.util.LookupUtils; -import com.sun.hotspot.igv.data.ChangedListener; -import com.sun.hotspot.igv.data.Group; -import com.sun.hotspot.igv.data.InputGraph; -import com.sun.hotspot.igv.util.RangeSliderModel; -import java.awt.BorderLayout; -import java.awt.CardLayout; -import java.awt.Component; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.*; -import java.util.prefs.Preferences; -import javax.swing.*; -import org.openide.awt.Toolbar; -import org.openide.util.Lookup; -import org.openide.util.NbBundle; -import org.openide.util.NbPreferences; -import org.openide.util.Utilities; -import org.openide.util.actions.Presenter; -import org.openide.util.lookup.AbstractLookup; -import org.openide.util.lookup.InstanceContent; -import org.openide.util.lookup.Lookups; -import org.openide.util.lookup.ProxyLookup; -import org.openide.windows.Mode; -import org.openide.windows.TopComponent; -import org.openide.windows.WindowManager; - -public final class EditorTopComponent extends TopComponent { - - private InstanceContent content; - private static final String PREFERRED_ID = "EditorTopComponent"; - private RangeSliderModel rangeSliderModel; - private CompilationViewer activeViewer; - private CompilationViewerFactory activeFactory; - private Group group; - private final JToolBar viewerToolBar; - private final JPanel viewerPanel; - private final CardLayout viewerPanelCardLayout; - private final Map createdComponents = new HashMap<>(); - private final Lookup proxyLookup; - private Lookup currentLookup = Lookups.fixed(); - private final Lookup.Provider currentViewLookupProvider = new Lookup.Provider() { - - @Override - public Lookup getLookup() { - return currentLookup; - } - }; - private static final String PREFERENCE_FACTORY = "factory"; - - public static Preferences getPreferences() { - return NbPreferences.forModule(EditorTopComponent.class); - } - - private InputGraph getFirstGraph() { - return group.getGraphs().get(getModel().getFirstPosition()); - } - - private InputGraph getSecondGraph() { - return group.getGraphs().get(getModel().getSecondPosition()); - } - - private void updateDisplayName() { - int first = getModel().getFirstPosition(); - int second = getModel().getSecondPosition(); - if (first == second) { - setDisplayName(getModel().getPositions().get(first)); - } else { - setDisplayName(String.format("%s: %s - %s", activeFactory.getName(), getModel().getPositions().get(first), getModel().getPositions().get(second))); - } - } - - private void activateFactory(CompilationViewerFactory factory) { - this.activeFactory = factory; - getPreferences().put(PREFERENCE_FACTORY, activeFactory.getName()); - updateView(); - } - - public EditorTopComponent(InputGraph graph) { - setName(NbBundle.getMessage(EditorTopComponent.class, "CTL_EditorTopComponent")); - setToolTipText(NbBundle.getMessage(EditorTopComponent.class, "HINT_EditorTopComponent")); - - initComponents(); - - Toolbar toolBar = new Toolbar(); - this.add(BorderLayout.NORTH, toolBar); - - this.group = graph.getGroup(); - rangeSliderModel = new RangeSliderModel(calculateStringList(group)); - content = new InstanceContent(); - content.add(rangeSliderModel); - int graphPos = group.getGraphs().indexOf(graph); - rangeSliderModel.setPositions(graphPos, graphPos); - - Collection factories = Lookup.getDefault().lookupAll(CompilationViewerFactory.class); - proxyLookup = Lookups.proxy(currentViewLookupProvider); - this.associateLookup(new ProxyLookup(new Lookup[]{proxyLookup, new AbstractLookup(content)})); - - rangeSliderModel.getChangedEvent().addListener(rangeSliderListener); - - ButtonGroup factoryButtonGroup = new ButtonGroup(); - for (CompilationViewerFactory factory : factories) { - AbstractButton button = createFactoryChangeButton(factory); - factoryButtonGroup.add(button); - toolBar.add(button); - } - toolBar.addSeparator(); - - viewerToolBar = new JToolBar(); - viewerToolBar.setFloatable(false); - toolBar.add(viewerToolBar); - toolBar.add(Box.createHorizontalGlue()); - - Action action = Utilities.actionsForPath("QuickSearchShadow").get(0); - Component quicksearch = ((Presenter.Toolbar) action).getToolbarPresenter(); - quicksearch.setMinimumSize(quicksearch.getPreferredSize()); // necessary for GTK LAF - toolBar.add(quicksearch); - - viewerPanel = new JPanel(); - viewerPanelCardLayout = new CardLayout(); - viewerPanel.setLayout(viewerPanelCardLayout); - this.add(viewerPanel, BorderLayout.CENTER); - - if (factories.size() > 0) { - String activeFactoryName = getPreferences().get(PREFERENCE_FACTORY, factories.iterator().next().getName()); - Enumeration buttons = factoryButtonGroup.getElements(); - for (CompilationViewerFactory factory : factories) { - JToggleButton curButton = (JToggleButton) buttons.nextElement(); - if (factory.getName().equals(activeFactoryName)) { - activeFactory = factory; - curButton.setSelected(true); - } - } - } - updateView(); - } - - private static List calculateStringList(Group g) { - List result = new ArrayList<>(); - for (InputGraph graph : g.getGraphs()) { - result.add(graph.getName()); - } - return result; - } - - private RangeSliderModel getModel() { - return rangeSliderModel; - } - - public static EditorTopComponent getActive() { - Set modes = WindowManager.getDefault().getModes(); - for (Mode m : modes) { - TopComponent tc = m.getSelectedTopComponent(); - if (tc instanceof EditorTopComponent) { - return (EditorTopComponent) tc; - } - } - return null; - } - - /** - * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - // //GEN-BEGIN:initComponents - private void initComponents() { - - jCheckBox1 = new javax.swing.JCheckBox(); - - org.openide.awt.Mnemonics.setLocalizedText(jCheckBox1, "jCheckBox1"); - jCheckBox1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0)); - jCheckBox1.setMargin(new java.awt.Insets(0, 0, 0, 0)); - - setLayout(new java.awt.BorderLayout()); - }// //GEN-END:initComponents - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JCheckBox jCheckBox1; - // End of variables declaration//GEN-END:variables - - @Override - public int getPersistenceType() { - return TopComponent.PERSISTENCE_NEVER; - } - - @Override - public void componentOpened() { - } - - @Override - public void componentClosed() { - } - - @Override - protected String preferredID() { - return PREFERRED_ID; - } - private ChangedListener rangeSliderListener = new ChangedListener() { - - @Override - public void changed(RangeSliderModel source) { - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - updateView(); - } - }); - } - }; - - private void updateView() { - updateDisplayName(); - String id = getViewStringIdentifier(); - if (!createdComponents.containsKey(id)) { - CompilationViewer newViewer = createViewer(activeFactory); - createdComponents.put(id, newViewer); - viewerPanel.add(newViewer.getComponent(), id); - } - - CompilationViewer newViewer = createdComponents.get(id); - if (newViewer != activeViewer) { - activeViewer = newViewer; - viewerPanelCardLayout.show(viewerPanel, id); - - currentLookup = new ProxyLookup(activeViewer.getLookup(), Lookups.fixed(getFirstGraph(), getSecondGraph())); - initializeToolBar(activeFactory.getName()); - - // Make sure that lookup is updated. - proxyLookup.lookup(Object.class); - } - } - - private String getViewStringIdentifier() { - return String.format("%s/%d/%d", activeFactory.getName(), getModel().getFirstPosition(), getModel().getSecondPosition()); - } - - private AbstractButton createFactoryChangeButton(final CompilationViewerFactory factory) { - JToggleButton toggleButton = new JToggleButton(factory.getName()); - toggleButton.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - activateFactory(factory); - } - }); - return toggleButton; - } - - private CompilationViewer createViewer(CompilationViewerFactory activeFactory) { - InputGraph firstSnapshot = getFirstGraph(); - InputGraph secondSnapshot = getSecondGraph(); - return activeFactory.createViewer(firstSnapshot, secondSnapshot); - } - - private void initializeToolBar(String id) { - viewerToolBar.removeAll(); - for (Action a : LookupUtils.lookupActions(String.format("CompilationViewer/%s/Actions", id), activeViewer.getLookup())) { - if (a instanceof Presenter.Toolbar) { - viewerToolBar.add(((Presenter.Toolbar) a).getToolbarPresenter()); - } else { - viewerToolBar.add(a); - } - } - viewerToolBar.updateUI(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Editor/src/com/oracle/graal/visualizer/editor/GraphViewerImplementation.java --- a/visualizer/Editor/src/com/oracle/graal/visualizer/editor/GraphViewerImplementation.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.oracle.graal.visualizer.editor; - -import com.sun.hotspot.igv.data.InputGraph; -import com.sun.hotspot.igv.data.services.GraphViewer; - -/** - * - * @author Thomas Wuerthinger - */ -public class GraphViewerImplementation implements GraphViewer { - - @Override - public void view(InputGraph graph) { - EditorTopComponent tc = new EditorTopComponent(graph); - tc.open(); - tc.requestActive(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Editor/src/com/oracle/graal/visualizer/editor/NodeQuickSearch.java --- a/visualizer/Editor/src/com/oracle/graal/visualizer/editor/NodeQuickSearch.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.oracle.graal.visualizer.editor; - -import com.sun.hotspot.igv.data.InputNode; -import com.sun.hotspot.igv.data.Properties; -import com.sun.hotspot.igv.data.Properties.RegexpPropertyMatcher; -import com.sun.hotspot.igv.data.services.InputGraphProvider; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.regex.Pattern; -import org.netbeans.spi.quicksearch.SearchProvider; -import org.netbeans.spi.quicksearch.SearchRequest; -import org.netbeans.spi.quicksearch.SearchResponse; -import org.openide.DialogDisplayer; -import org.openide.NotifyDescriptor; -import org.openide.NotifyDescriptor.Message; - -/** - * - * @author Thomas Wuerthinger - */ -public class NodeQuickSearch implements SearchProvider { - - private static final String DEFAULT_PROPERTY = "name"; - - /** - * Method is called by infrastructure when search operation was requested. - * Implementors should evaluate given request and fill response object with - * apropriate results - * - * @param request Search request object that contains information what to search for - * @param response Search response object that stores search results. Note that it's important to react to return value of SearchResponse.addResult(...) method and stop computation if false value is returned. - */ - @Override - public void evaluate(SearchRequest request, SearchResponse response) { - String query = request.getText(); - if (query.trim().isEmpty()) { - return; - } - - final String[] parts = query.split("=", 2); - - String name; - String value; - - if (parts.length == 1) { - name = DEFAULT_PROPERTY; - value = ".*" + Pattern.quote(parts[0]) + ".*"; - } else { - name = parts[0]; - value = parts[1]; - } - - if (value.isEmpty()) { - value = ".*"; - } - - final InputGraphProvider p = null;// TODO: FIXME LookupHistory.getLast(InputGraphProvider.class); - if (p != null && p.getGraph() != null) { - List matches = null; - try { - RegexpPropertyMatcher matcher = new RegexpPropertyMatcher(name, value, Pattern.CASE_INSENSITIVE); - Properties.PropertySelector selector = new Properties.PropertySelector<>(p.getGraph().getNodes()); - - matches = selector.selectMultiple(matcher); - } catch (Exception e) { - final String msg = e.getMessage(); - response.addResult(new Runnable() { - @Override - public void run() { - Message desc = new NotifyDescriptor.Message("An exception occurred during the search, " - + "perhaps due to a malformed query string:\n" + msg, - NotifyDescriptor.WARNING_MESSAGE); - DialogDisplayer.getDefault().notify(desc); - } - }, - "(Error during search)" - ); - } - - if (matches != null) { - final Set set = new HashSet<>(matches); - response.addResult(new Runnable() { - @Override - public void run() { - final EditorTopComponent comp = EditorTopComponent.getActive(); - if (comp != null) { - // TODO: find connection again! - //comp.setSelectedNodes(set); - comp.requestActive(); - } - } - }, - "All " + matches.size() + " matching nodes (" + name + "=" + value + ")" - ); - - // Single matches - for (final InputNode n : matches) { - response.addResult(new Runnable() { - @Override - public void run() { - final EditorTopComponent comp = EditorTopComponent.getActive(); - if (comp != null) { - final Set tmpSet = new HashSet<>(); - tmpSet.add(n); - // TODO: find connection again! - //comp.setSelectedNodes(tmpSet); - comp.requestActive(); - } - } - }, - n.getProperties().get(name) + " (" + n.getId() + " " + n.getProperties().get("name") + ")" - ); - } - } - } else { - System.out.println("no input graph provider!"); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Editor/src/com/oracle/graal/visualizer/editor/SplitCompilationViewer.java --- a/visualizer/Editor/src/com/oracle/graal/visualizer/editor/SplitCompilationViewer.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.oracle.graal.visualizer.editor; - -import com.sun.hotspot.igv.graph.Figure; -import java.awt.BorderLayout; -import java.awt.Component; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.Collection; -import java.util.prefs.Preferences; -import javax.swing.JPanel; -import javax.swing.JSplitPane; -import javax.swing.JToolBar; -import org.openide.util.Lookup; -import org.openide.util.NbPreferences; -import org.openide.util.lookup.Lookups; -import org.openide.util.lookup.ProxyLookup; - -class SplitCompilationViewer implements CompilationViewer { - - private JSplitPane splitPane; - private Component firstPanel; - private Component secondPanel; - private Lookup combinedLookup; - private static final String DIVIDER_LOCATION = "dividerLocation"; - private final PropertyChangeListener splitChanged = new PropertyChangeListener() { - - @Override - public void propertyChange(PropertyChangeEvent changeEvent) { - String propertyName = changeEvent.getPropertyName(); - if (propertyName.equals(JSplitPane.DIVIDER_LOCATION_PROPERTY)) { - setLastDividerLocation((Integer) changeEvent.getNewValue()); - } - } - }; - - private static void setLastDividerLocation(int pos) { - NbPreferences.forModule(SplitCompilationViewer.class).put(DIVIDER_LOCATION, Integer.toString(pos)); - } - - private static int getLastDividerLocation() { - try { - return Integer.parseInt(NbPreferences.forModule(SplitCompilationViewer.class).get(DIVIDER_LOCATION, "400")); - } catch (NumberFormatException e) { - return 400; - } - } - - public SplitCompilationViewer(CompilationViewer firstViewer, CompilationViewer secondViewer) { - splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); - firstPanel = createComponent(firstViewer); - secondPanel = createComponent(secondViewer); - splitPane.add(firstPanel); - splitPane.add(secondPanel); - splitPane.addPropertyChangeListener(splitChanged); - splitPane.setDividerLocation(getLastDividerLocation()); - combinedLookup = new ProxyLookup(firstViewer.getLookup(), secondViewer.getLookup()); - } - - @Override - public Lookup getLookup() { - return combinedLookup; - } - - @Override - public Component getComponent() { - return splitPane; - } - - private Component createComponent(CompilationViewer viewer) { - return viewer.getComponent(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Editor/src/com/oracle/graal/visualizer/editor/SplitCompilationViewerFactory.java --- a/visualizer/Editor/src/com/oracle/graal/visualizer/editor/SplitCompilationViewerFactory.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.editor; - -import com.sun.hotspot.igv.data.InputGraph; - -public abstract class SplitCompilationViewerFactory implements CompilationViewerFactory { - - @Override - public CompilationViewer createViewer(InputGraph firstGraph, InputGraph secondGraph) { - if (firstGraph == secondGraph) { - return createViewer(firstGraph); - } else { - CompilationViewer firstViewer = createViewer(firstGraph); - CompilationViewer secondViewer = createViewer(secondGraph); - return new SplitCompilationViewer(firstViewer, secondViewer); - } - } - - protected abstract CompilationViewer createViewer(InputGraph graph); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Editor/src/com/oracle/graal/visualizer/editor/layer.xml --- a/visualizer/Editor/src/com/oracle/graal/visualizer/editor/layer.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/build.xml --- a/visualizer/Filter/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project com.sun.hotspot.igv.filter. - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/manifest.mf --- a/visualizer/Filter/manifest.mf Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.sun.hotspot.igv.filter -OpenIDE-Module-Layer: com/sun/hotspot/igv/filter/layer.xml -OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/filter/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/nbproject/build-impl.xml --- a/visualizer/Filter/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/nbproject/genfiles.properties --- a/visualizer/Filter/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -build.xml.data.CRC32=7c032ebf -build.xml.script.CRC32=3b022a25 -build.xml.stylesheet.CRC32=79c3b980 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=7c032ebf -nbproject/build-impl.xml.script.CRC32=26513f91 -nbproject/build-impl.xml.stylesheet.CRC32=deb65f65 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/nbproject/platform.properties --- a/visualizer/Filter/nbproject/platform.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -# Deprecated since 5.0u1; for compatibility with 5.0: -disabled.clusters=\ - apisupport1,\ - harness,\ - ide8,\ - java1,\ - nb6.0,\ - profiler2 -disabled.modules=\ - org.netbeans.core.execution,\ - org.netbeans.core.multiview,\ - org.netbeans.core.output2,\ - org.netbeans.modules.applemenu,\ - org.netbeans.modules.autoupdate.services,\ - org.netbeans.modules.autoupdate.ui,\ - org.netbeans.modules.core.kit,\ - org.netbeans.modules.favorites,\ - org.netbeans.modules.javahelp,\ - org.netbeans.modules.masterfs,\ - org.netbeans.modules.options.keymap,\ - org.netbeans.modules.sendopts,\ - org.netbeans.modules.templates,\ - org.openide.compat,\ - org.openide.execution,\ - org.openide.util.enumerations -enabled.clusters=\ - platform7 -nbjdk.active=JDK_1.6 -nbplatform.active=default diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/nbproject/project.properties --- a/visualizer/Filter/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -javac.source=1.7 -javac.compilerargs=-Xlint -Xlint:-serial diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/nbproject/project.xml --- a/visualizer/Filter/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - com.sun.hotspot.igv.filter - - - - com.sun.hotspot.igv.data - - - - 1.0 - - - - com.sun.hotspot.igv.graph - - - - 1.0 - - - - com.sun.hotspot.igv.layout - - - - 1.0 - - - - org.jdesktop.layout - - - - 1 - 1.16.1 - - - - org.openide.awt - - - - 7.30.1 - - - - org.openide.dialogs - - - - 7.18.1 - - - - org.openide.filesystems - - - - 7.46.1 - - - - org.openide.nodes - - - - 7.20.1 - - - - org.openide.util - - - - 8.14.1 - - - - org.openide.util.lookup - - - - 8.6.1 - - - - org.openide.windows - - - - 6.39.1 - - - - - com.sun.hotspot.igv.filter - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/nbproject/suite.properties --- a/visualizer/Filter/nbproject/suite.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -suite.dir=${basedir}/.. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/AbstractFilter.java --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/AbstractFilter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 com.sun.hotspot.igv.filter; - -import com.sun.hotspot.igv.data.ChangedEvent; -import com.sun.hotspot.igv.data.Properties; -import org.openide.cookies.OpenCookie; - -/** - * - * @author Thomas Wuerthinger - */ -public abstract class AbstractFilter implements Filter { - - private ChangedEvent changedEvent; - private Properties properties; - - public AbstractFilter() { - changedEvent = new ChangedEvent(this); - properties = new Properties(); - } - - @Override - public Properties getProperties() { - return properties; - } - - @Override - public OpenCookie getEditor() { - return null; - } - - @Override - public ChangedEvent getChangedEvent() { - return changedEvent; - } - - protected void fireChangedEvent() { - changedEvent.fire(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/Bundle.properties --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -OpenIDE-Module-Name=Filter - -jLabel1.text=Name\: -jLabel2.text=Source\: - -nameTextField.text= - -jButton1.text=OK -jButton2.text=Cancel - -title=Edit Filter Dialog diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/ColorFilter.java --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/ColorFilter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filter; - -import com.sun.hotspot.igv.data.Properties; -import com.sun.hotspot.igv.graph.Connection.ConnectionStyle; -import com.sun.hotspot.igv.graph.*; -import java.awt.Color; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public class ColorFilter extends AbstractFilter { - - private List colorRules; - private String name; - - public ColorFilter(String name) { - this.name = name; - colorRules = new ArrayList<>(); - } - - @Override - public String getName() { - return name; - } - - @Override - public void apply(Diagram diagram) { - - Properties.PropertySelector
selector = new Properties.PropertySelector<>(diagram.getFigures()); - for (ColorRule rule : colorRules) { - if (rule.getSelector() != null) { - List
figures = rule.getSelector().selected(diagram); - for (Figure f : figures) { - applyRule(rule, f); - if (rule.getColor() != null) { - f.setColor(rule.getColor()); - } - } - } else { - for (Figure f : diagram.getFigures()) { - applyRule(rule, f); - } - } - } - } - - private void applyRule(ColorRule rule, Figure f) { - if (rule.getColor() != null) { - f.setColor(rule.getColor()); - } - Color color = rule.getLineColor(); - ConnectionStyle style = rule.getLineStyle(); - - for (OutputSlot s : f.getOutputSlots()) { - for (Connection c : s.getConnections()) { - if (color != null) { - c.setColor(color); - } - - if (style != null) { - c.setStyle(style); - } - } - } - } - - public void addRule(ColorRule r) { - colorRules.add(r); - } - - public static class ColorRule { - - private Color color; - private Color lineColor; - private Connection.ConnectionStyle lineStyle; - private Selector selector; - - public ColorRule(Selector selector, Color c) { - this(selector, c, null, null); - } - - public ColorRule(Selector selector, Color c, Color lineColor, Connection.ConnectionStyle lineStyle) { - this.selector = selector; - this.color = c; - this.lineColor = lineColor; - this.lineStyle = lineStyle; - - } - - public ColorRule(Color c) { - this(null, c); - } - - public Color getColor() { - return color; - } - - public Selector getSelector() { - return selector; - } - - public Color getLineColor() { - return lineColor; - } - - public Connection.ConnectionStyle getLineStyle() { - return lineStyle; - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/CombineFilter.java --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/CombineFilter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,221 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filter; - -import com.sun.hotspot.igv.data.Properties; -import com.sun.hotspot.igv.data.Properties.PropertyMatcher; -import com.sun.hotspot.igv.graph.*; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * - * @author Thomas Wuerthinger - */ -public class CombineFilter extends AbstractFilter { - - private List rules; - private String name; - - public CombineFilter(String name) { - this.name = name; - rules = new ArrayList<>(); - } - - @Override - public String getName() { - return name; - } - - @Override - public void apply(Diagram diagram) { - - Properties.PropertySelector
selector = new Properties.PropertySelector<>(diagram.getFigures()); - for (CombineRule r : rules) { - - List
list = selector.selectMultiple(r.getFirstMatcher()); - Set
figuresToRemove = new HashSet<>(); - for (Figure f : list) { - - List
successors = new ArrayList<>(f.getSuccessors()); - if (r.isReversed()) { - if (successors.size() == 1) { - Figure succ = successors.get(0); - InputSlot slot = null; - - for (InputSlot s : succ.getInputSlots()) { - for (Connection c : s.getConnections()) { - if (c.getOutputSlot().getFigure() == f) { - slot = s; - } - } - } - - slot.getSource().addSourceNodes(f.getSource()); - if (r.getShortProperty() != null) { - String s = f.getProperties().get(r.getShortProperty()); - if (s != null && s.length() > 0) { - slot.setShortName(s); - slot.setText(s); - slot.setColor(f.getColor()); - } - } else { - assert slot != null; - slot.setText(f.getProperties().get("dump_spec")); - if (f.getProperties().get("short_name") != null) { - slot.setShortName(f.getProperties().get("short_name")); - } else { - String s = f.getProperties().get("dump_spec"); - if (s != null && s.length() <= 5) { - slot.setShortName(s); - } - } - } - - for (InputSlot s : f.getInputSlots()) { - for (Connection c : s.getConnections()) { - Connection newConn = diagram.createConnection(slot, c.getOutputSlot(), c.getLabel()); - newConn.setColor(c.getColor()); - newConn.setStyle(c.getStyle()); - } - } - - figuresToRemove.add(f); - } - } else { - - for (Figure succ : successors) { - if (succ.getPredecessors().size() == 1 && succ.getInputSlots().size() == 1) { - if (succ.getProperties().selectSingle(r.getSecondMatcher()) != null && succ.getOutputSlots().size() == 1) { - - - OutputSlot oldSlot = null; - for (OutputSlot s : f.getOutputSlots()) { - for (Connection c : s.getConnections()) { - if (c.getInputSlot().getFigure() == succ) { - oldSlot = s; - } - } - } - - assert oldSlot != null; - - OutputSlot nextSlot = succ.getOutputSlots().get(0); - int pos = 0; - if (succ.getProperties().get("con") != null) { - pos = Integer.parseInt(succ.getProperties().get("con")); - } - OutputSlot slot = f.createOutputSlot(pos); - slot.getSource().addSourceNodes(succ.getSource()); - if (r.getShortProperty() != null) { - String s = succ.getProperties().get(r.getShortProperty()); - if (s != null && s.length() > 0) { - slot.setShortName(s); - slot.setText(s); - slot.setColor(succ.getColor()); - } - } else { - slot.setText(succ.getProperties().get("dump_spec")); - if (succ.getProperties().get("short_name") != null) { - slot.setShortName(succ.getProperties().get("short_name")); - } else { - String s = succ.getProperties().get("dump_spec"); - if (s != null && s.length() <= 2) { - slot.setShortName(s); - } else { - String tmpName = succ.getProperties().get("name"); - if (tmpName != null && tmpName.length() > 0) { - slot.setShortName(tmpName.substring(0, 1)); - } - } - } - } - for (Connection c : nextSlot.getConnections()) { - Connection newConn = diagram.createConnection(c.getInputSlot(), slot, c.getLabel()); - newConn.setColor(c.getColor()); - newConn.setStyle(c.getStyle()); - } - - - figuresToRemove.add(succ); - - if (oldSlot.getConnections().size() == 0) { - f.removeSlot(oldSlot); - } - } - } - } - } - } - - diagram.removeAllFigures(figuresToRemove); - } - } - - public void addRule(CombineRule combineRule) { - rules.add(combineRule); - } - - public static class CombineRule { - - private PropertyMatcher first; - private PropertyMatcher second; - private boolean reversed; - private String shortProperty; - - public CombineRule(PropertyMatcher first, PropertyMatcher second) { - this(first, second, false); - - } - - public CombineRule(PropertyMatcher first, PropertyMatcher second, boolean reversed) { - this(first, second, reversed, null); - } - - public CombineRule(PropertyMatcher first, PropertyMatcher second, boolean reversed, String shortProperty) { - this.first = first; - this.second = second; - this.reversed = reversed; - this.shortProperty = shortProperty; - } - - public boolean isReversed() { - return reversed; - } - - public PropertyMatcher getFirstMatcher() { - return first; - } - - public PropertyMatcher getSecondMatcher() { - return second; - } - - public String getShortProperty() { - return shortProperty; - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/ConnectionFilter.java --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/ConnectionFilter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filter; - -import com.sun.hotspot.igv.data.Properties; -import com.sun.hotspot.igv.graph.*; -import java.awt.Color; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public class ConnectionFilter extends AbstractFilter { - - private List connectionStyleRules; - private String name; - - public ConnectionFilter(String name) { - this.name = name; - connectionStyleRules = new ArrayList<>(); - } - - @Override - public String getName() { - return name; - } - - @Override - public void apply(Diagram diagram) { - - Properties.PropertySelector
selector = new Properties.PropertySelector<>(diagram.getFigures()); - for (ConnectionStyleRule rule : connectionStyleRules) { - List
figures = null; - if (rule.getSelector() != null) { - figures = rule.getSelector().selected(diagram); - } else { - figures = diagram.getFigures(); - } - - for (Figure f : figures) { - for (OutputSlot os : f.getOutputSlots()) { - for (Connection c : os.getConnections()) { - if (figures.contains(c.getInputSlot().getFigure())) { - c.setStyle(rule.getLineStyle()); - c.setColor(rule.getLineColor()); - } - } - } - } - } - } - - public void addRule(ConnectionStyleRule r) { - connectionStyleRules.add(r); - } - - public static class ConnectionStyleRule { - - private Color lineColor; - private Connection.ConnectionStyle lineStyle; - private Selector selector; - - public ConnectionStyleRule(Selector selector, Color lineColor, Connection.ConnectionStyle lineStyle) { - this.selector = selector; - this.lineColor = lineColor; - this.lineStyle = lineStyle; - } - - public Selector getSelector() { - return selector; - } - - public Color getLineColor() { - return lineColor; - } - - public Connection.ConnectionStyle getLineStyle() { - return lineStyle; - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/CustomFilter.java --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/CustomFilter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,138 +0,0 @@ -/* - * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 com.sun.hotspot.igv.filter; - -import com.sun.hotspot.igv.graph.Diagram; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.script.*; -import org.openide.cookies.OpenCookie; -import org.openide.filesystems.FileObject; -import org.openide.filesystems.FileUtil; -import org.openide.util.Exceptions; - -/** - * - * @author Thomas Wuerthinger - */ -public class CustomFilter extends AbstractFilter { - - public static final String JAVASCRIPT_HELPER_ID = "JavaScriptHelper"; - private String code; - private String name; - - public CustomFilter(String name, String code) { - this.name = name; - this.code = code; - getProperties().setProperty("name", name); - } - - @Override - public String getName() { - return name; - } - - public String getCode() { - return code; - } - - public void setName(String s) { - name = s; - fireChangedEvent(); - } - - public void setCode(String s) { - code = s; - fireChangedEvent(); - } - - @Override - public OpenCookie getEditor() { - return new OpenCookie() { - - @Override - public void open() { - openInEditor(); - } - }; - } - - public boolean openInEditor() { - EditFilterDialog dialog = new EditFilterDialog(CustomFilter.this); - dialog.setVisible(true); - boolean result = dialog.wasAccepted(); - this.getChangedEvent().fire(); - return result; - } - - @Override - public String toString() { - return getName(); - } - - private static String getJsHelperText() { - InputStream is = null; - StringBuilder sb = new StringBuilder("importPackage(Packages.com.sun.hotspot.igv.filter);importPackage(Packages.com.sun.hotspot.igv.graph);importPackage(Packages.com.sun.hotspot.igv.data);importPackage(Packages.com.sun.hotspot.igv.util);importPackage(java.awt);"); - try { - FileObject fo = FileUtil.getConfigRoot().getFileObject(JAVASCRIPT_HELPER_ID); - is = fo.getInputStream(); - BufferedReader r = new BufferedReader(new InputStreamReader(is)); - String s; - while ((s = r.readLine()) != null) { - sb.append(s); - sb.append("\n"); - } - - } catch (IOException ex) { - Logger.getLogger("global").log(Level.SEVERE, null, ex); - } finally { - try { - is.close(); - } catch (IOException ex) { - Exceptions.printStackTrace(ex); - } - } - return sb.toString(); - } - - @Override - public void apply(Diagram d) { - try { - ScriptEngineManager sem = new ScriptEngineManager(); - ScriptEngine e = sem.getEngineByName("ECMAScript"); - e.eval(getJsHelperText()); - Bindings b = e.getContext().getBindings(ScriptContext.ENGINE_SCOPE); - b.put("graph", d); - b.put("IO", System.out); - e.eval(code, b); - } catch (ScriptException ex) { - Exceptions.printStackTrace(ex); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/EdgeColorIndexFilter.java --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/EdgeColorIndexFilter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filter; - -import com.sun.hotspot.igv.graph.*; -import java.awt.Color; -import java.util.List; - -public class EdgeColorIndexFilter extends AbstractFilter { - - public static final String INPUTS = "INPUTS"; - public static final String OUTPUTS = "OUTPUTS"; - private final String applyTo; - private final Color[] colors; - - public EdgeColorIndexFilter(String applyTo, Color... color) { - if (!applyTo.equals(INPUTS) && !applyTo.equals(OUTPUTS)) { - throw new IllegalArgumentException("applyTo"); - } - - this.applyTo = applyTo; - this.colors = color; - } - - @Override - public String getName() { - return "Edge Color Index Filter"; - } - - @Override - public void apply(Diagram d) { - List
figures = d.getFigures(); - for (Figure f : figures) { - Slot[] slots; - if (applyTo.equals(INPUTS)) { - List inputSlots = f.getInputSlots(); - slots = inputSlots.toArray(new Slot[inputSlots.size()]); - } else { - List outputSlots = f.getOutputSlots(); - slots = outputSlots.toArray(new Slot[outputSlots.size()]); - } - int index = 0; - for (Slot slot : slots) { - if (index < colors.length && colors[index] != null) { - slot.setColor(colors[index]); - for (Connection c : slot.getConnections()) { - - c.setColor(colors[index]); - } - } - index++; - } - - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/EditFilterDialog.form --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/EditFilterDialog.form Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/EditFilterDialog.java --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/EditFilterDialog.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +0,0 @@ -/* - * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 com.sun.hotspot.igv.filter; - -import org.openide.windows.WindowManager; - -/** - * - * @author Thomas Wuerthinger - */ -public class EditFilterDialog extends javax.swing.JDialog { - - private CustomFilter customFilter; - private boolean accepted; - - /** Creates new form EditFilterDialog */ - public EditFilterDialog(CustomFilter customFilter) { - super(WindowManager.getDefault().getMainWindow(), true); - this.customFilter = customFilter; - initComponents(); - - sourceTextArea.setText(customFilter.getCode()); - nameTextField.setText(customFilter.getName()); - } - - public boolean wasAccepted() { - return accepted; - } - - /** This method is called from within the constructor to - * initialize the form. - * WARNING: Do NOT modify this code. The content of this method is - * always regenerated by the Form Editor. - */ - // //GEN-BEGIN:initComponents - private void initComponents() { - - jScrollPane1 = new javax.swing.JScrollPane(); - sourceTextArea = new javax.swing.JTextArea(); - nameTextField = new javax.swing.JTextField(); - nameLabel = new javax.swing.JLabel(); - sourceLabel = new javax.swing.JLabel(); - okButton = new javax.swing.JButton(); - cancelButton = new javax.swing.JButton(); - - setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); - setTitle(org.openide.util.NbBundle.getMessage(EditFilterDialog.class, "title")); // NOI18N - setResizable(false); - - sourceTextArea.setColumns(20); - sourceTextArea.setRows(5); - jScrollPane1.setViewportView(sourceTextArea); - - nameTextField.setText("null"); - - nameLabel.setText(org.openide.util.NbBundle.getMessage(EditFilterDialog.class, "jLabel1.text")); // NOI18N - - sourceLabel.setText(org.openide.util.NbBundle.getMessage(EditFilterDialog.class, "jLabel2.text")); // NOI18N - - okButton.setText(org.openide.util.NbBundle.getMessage(EditFilterDialog.class, "jButton1.text")); // NOI18N - okButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - cancelButtonClicked(evt); - okButtonClicked(evt); - } - }); - - cancelButton.setText(org.openide.util.NbBundle.getMessage(EditFilterDialog.class, "jButton2.text")); // NOI18N - cancelButton.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - cancelButtonClicked(evt); - } - }); - - org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane()); - getContentPane().setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(layout.createSequentialGroup() - .addContainerGap() - .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup() - .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(sourceLabel) - .add(nameLabel)) - .add(25, 25, 25) - .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 695, Short.MAX_VALUE) - .add(nameTextField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 695, Short.MAX_VALUE))) - .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup() - .add(okButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 76, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) - .add(cancelButton))) - .addContainerGap()) - ); - layout.setVerticalGroup( - layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(layout.createSequentialGroup() - .addContainerGap() - .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) - .add(nameLabel) - .add(nameTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED) - .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(sourceLabel) - .add(jScrollPane1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 337, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) - .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 16, Short.MAX_VALUE) - .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) - .add(cancelButton) - .add(okButton)) - .addContainerGap()) - ); - - pack(); - }// //GEN-END:initComponents - -private void okButtonClicked(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonClicked - this.customFilter.setName(this.nameTextField.getText()); - this.customFilter.setCode(this.sourceTextArea.getText()); - accepted = true; - setVisible(false); -}//GEN-LAST:event_okButtonClicked - -private void cancelButtonClicked(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonClicked - setVisible(false); -}//GEN-LAST:event_cancelButtonClicked - - - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JButton cancelButton; - private javax.swing.JScrollPane jScrollPane1; - private javax.swing.JLabel nameLabel; - private javax.swing.JTextField nameTextField; - private javax.swing.JButton okButton; - private javax.swing.JLabel sourceLabel; - private javax.swing.JTextArea sourceTextArea; - // End of variables declaration//GEN-END:variables - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/Filter.java --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/Filter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filter; - -import com.sun.hotspot.igv.data.ChangedEvent; -import com.sun.hotspot.igv.data.ChangedEventProvider; -import com.sun.hotspot.igv.data.Properties; -import com.sun.hotspot.igv.graph.Diagram; -import org.openide.cookies.OpenCookie; - -/** - * - * @author Thomas Wuerthinger - */ -public interface Filter extends Properties.Provider, ChangedEventProvider { - - public String getName(); - - public void apply(Diagram d); - - OpenCookie getEditor(); - - @Override - ChangedEvent getChangedEvent(); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/FilterChain.java --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/FilterChain.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filter; - -import com.sun.hotspot.igv.data.ChangedEvent; -import com.sun.hotspot.igv.data.ChangedEventProvider; -import com.sun.hotspot.igv.data.ChangedListener; -import com.sun.hotspot.igv.graph.Diagram; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public class FilterChain implements ChangedEventProvider { - - private List filters; - private transient ChangedEvent changedEvent; - - private ChangedListener changedListener = new ChangedListener() { - @Override - public void changed(Filter source) { - changedEvent.fire(); - } - }; - - public FilterChain() { - filters = new ArrayList<>(); - changedEvent = new ChangedEvent<>(this); - } - - public FilterChain(FilterChain f) { - this.filters = new ArrayList<>(f.filters); - changedEvent = new ChangedEvent<>(this); - } - - @Override - public ChangedEvent getChangedEvent() { - return changedEvent; - } - - public Filter getFilterAt(int index) { - assert index >= 0 && index < filters.size(); - return filters.get(index); - } - - public void apply(Diagram d) { - for (Filter f : filters) { - f.apply(d); - } - } - - public void apply(Diagram d, FilterChain sequence) { - List applied = new ArrayList<>(); - for (Filter f : sequence.getFilters()) { - if (filters.contains(f)) { - f.apply(d); - applied.add(f); - } - } - - - for (Filter f : filters) { - if (!applied.contains(f)) { - f.apply(d); - } - } - } - - - public void addFilter(Filter filter) { - assert filter != null; - filters.add(filter); - filter.getChangedEvent().addListener(changedListener); - changedEvent.fire(); - } - - public boolean containsFilter(Filter filter) { - return filters.contains(filter); - } - - public void removeFilter(Filter filter) { - assert filters.contains(filter); - filters.remove(filter); - filter.getChangedEvent().removeListener(changedListener); - changedEvent.fire(); - } - - public void moveFilterUp(Filter filter) { - assert filters.contains(filter); - int index = filters.indexOf(filter); - if (index != 0) { - filters.remove(index); - filters.add(index - 1, filter); - } - changedEvent.fire(); - } - - public void moveFilterDown(Filter filter) { - assert filters.contains(filter); - int index = filters.indexOf(filter); - if (index != filters.size() - 1) { - filters.remove(index); - filters.add(index + 1, filter); - } - changedEvent.fire(); - } - - public List getFilters() { - return Collections.unmodifiableList(filters); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/FilterChainProvider.java --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/FilterChainProvider.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filter; - -/** - * - * @author Thomas Wuerthinger - */ -public interface FilterChainProvider { - - public FilterChain getFilterChain(); - - public FilterChain getSequence(); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/FilterSetting.java --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/FilterSetting.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filter; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -/** - * - * @author Thomas Wuerthinger - */ -public class FilterSetting { - - private Set filters; - private String name; - - public FilterSetting() { - this(null); - } - - public FilterSetting(String name) { - this.name = name; - filters = new HashSet<>(); - } - - public Set getFilters() { - return Collections.unmodifiableSet(filters); - } - - public void addFilter(Filter f) { - assert !filters.contains(f); - filters.add(f); - } - - public void removeFilter(Filter f) { - assert filters.contains(f); - filters.remove(f); - } - - public boolean containsFilter(Filter f) { - return filters.contains(f); - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getFilterCount() { - return filters.size(); - } - - @Override - public String toString() { - return getName(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/GradientColorFilter.java --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/GradientColorFilter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filter; - -import com.sun.hotspot.igv.graph.Diagram; -import com.sun.hotspot.igv.graph.Figure; -import java.awt.*; -import java.awt.geom.AffineTransform; -import java.awt.image.Raster; -import java.util.List; - -/** - * Filter that colors nodes using a customizable color gradient, based on how - * a numeric property is located in a specified interval. - * - * @author Peter Hofer - */ -public class GradientColorFilter extends AbstractFilter { - - public static final String LINEAR = "LINEAR"; - public static final String LOGARITHMIC = "LOGARITHMIC"; - - private String propertyName = "probability"; - private float minValue = 0; - private float maxValue = 500; - private float[] fractions = {0, 0.5f, 1}; - private Color[] colors = {Color.BLUE, Color.YELLOW, Color.RED}; - private int shadeCount = 8; - private String mode = LINEAR; - - @Override - public String getName() { - return "Gradient Color Filter"; - } - - @Override - public void apply(Diagram d) { - boolean logarithmic = mode.equalsIgnoreCase(LOGARITHMIC); - if (!logarithmic && !mode.equalsIgnoreCase(LINEAR)) { - throw new RuntimeException("Unknown mode: " + mode); - } - - Rectangle bounds = new Rectangle(shadeCount, 1); - LinearGradientPaint lgp = new LinearGradientPaint(bounds.x, bounds.y, bounds.width, bounds.y, fractions, colors); - PaintContext context = lgp.createContext(null, bounds, bounds.getBounds2D(), AffineTransform.getTranslateInstance(0, 0), new RenderingHints(null)); - Raster raster = context.getRaster(bounds.x, bounds.y, bounds.width, bounds.height); - int[] rgb = raster.getPixels(bounds.x, bounds.y, bounds.width, bounds.height, (int[]) null); - Color[] shades = new Color[rgb.length / 3]; - for (int i = 0; i < shades.length; ++i) { - shades[i] = new Color(rgb[i * 3], rgb[i * 3 + 1], rgb[i * 3 + 2]); - } - - List
figures = d.getFigures(); - for (Figure f : figures) { - String property = f.getProperties().get(propertyName); - if (property != null) { - try { - float value = Float.parseFloat(property); - - Color nodeColor; - if (value <= minValue) { - nodeColor = colors[0]; - } else if (value >= maxValue) { - nodeColor = colors[colors.length - 1]; - } else { - double normalized = value - minValue; - double interval = maxValue - minValue; - int index; - // Use Math.ceil() to make values above zero distinguishable from zero - if (logarithmic) { - index = (int) Math.ceil(shades.length * Math.log(1 + normalized) / Math.log(1 + interval)); - } else { - index = (int) Math.ceil(shades.length * normalized / interval); - } - nodeColor = shades[index]; - } - f.setColor(nodeColor); - } catch (Exception e) { - e.printStackTrace(); - } - } - } - } - - public String getPropertyName() { - return propertyName; - } - - public void setPropertyName(String propertyName) { - this.propertyName = propertyName; - } - - public float getMinValue() { - return minValue; - } - - public void setMinValue(float minValue) { - this.minValue = minValue; - } - - public float getMaxValue() { - return maxValue; - } - - public void setMaxValue(float maxValue) { - this.maxValue = maxValue; - } - - public float[] getFractions() { - return fractions; - } - - public void setFractions(float[] fractions) { - this.fractions = fractions; - } - - public Color[] getColors() { - return colors; - } - - public void setColors(Color[] colors) { - this.colors = colors; - } - - public int getShadeCount() { - return shadeCount; - } - - public void setShadeCount(int shadeCount) { - this.shadeCount = shadeCount; - } - - public String getMode() { - return mode; - } - - public void setMode(String mode) { - this.mode = mode; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveFilter.java --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveFilter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filter; - -import com.sun.hotspot.igv.graph.Diagram; -import com.sun.hotspot.igv.graph.Figure; -import com.sun.hotspot.igv.graph.Selector; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * - * @author Thomas Wuerthinger - */ -public class RemoveFilter extends AbstractFilter { - - private List rules; - private String name; - - public RemoveFilter(String name) { - this.name = name; - rules = new ArrayList<>(); - } - - @Override - public String getName() { - return name; - } - - @Override - public void apply(Diagram diagram) { - for (RemoveRule r : rules) { - List
selected = r.getSelector().selected(diagram); - Set
toRemove = new HashSet<>(selected); - - if (r.getRemoveOrphans()) { - boolean changed; - do { - changed = false; - for (Figure f : diagram.getFigures()) { - if (!toRemove.contains(f)) { - if (toRemove.containsAll(f.getPredecessors()) && toRemove.containsAll(f.getSuccessors())) { - toRemove.add(f); - changed = true; - } - } - } - } while (changed); - } - - diagram.removeAllFigures(toRemove); - } - } - - public void addRule(RemoveRule rule) { - rules.add(rule); - } - - public static class RemoveRule { - - private Selector selector; - private boolean removeOrphans; - - public RemoveRule(Selector selector) { - this(selector, false); - } - - public RemoveRule(Selector selector, boolean removeOrphans) { - this.selector = selector; - this.removeOrphans = removeOrphans; - } - - public Selector getSelector() { - return selector; - } - - public boolean getRemoveOrphans() { - return removeOrphans; - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveInputsFilter.java --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveInputsFilter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filter; - -import com.sun.hotspot.igv.graph.*; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public class RemoveInputsFilter extends AbstractFilter { - - private List rules; - private String name; - - public RemoveInputsFilter(String name) { - this.name = name; - rules = new ArrayList<>(); - } - - @Override - public String getName() { - return name; - } - - @Override - public void apply(Diagram diagram) { - - for (RemoveInputsRule r : rules) { - - List
list = r.getSelector().selected(diagram); - for (Figure f : list) { - int z = 0; - List last = new ArrayList<>(); - for (InputSlot is : f.getInputSlots()) { - if (z >= r.getStartingIndex() && z <= r.getEndIndex() && is.getConnections().size() > 0) { - StringBuilder sb = new StringBuilder(); - List conns = is.getConnections(); - for (int i = 0; i < conns.size(); i++) { - Connection c = conns.get(i); - OutputSlot os = c.getOutputSlot(); - Figure pred = os.getFigure(); - if (i != 0) { - sb.append("
"); - } - sb.append(pred.getLines()[0]); - } - is.removeAllConnections(); - is.setShortName("X"); - is.setText(sb.toString()); - last.add(is); - } else { - last.clear(); - } - z++; - } - - if (last.size() > 3) { - InputSlot first = last.get(0); - first.setShortName("XX"); - - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < last.size(); i++) { - InputSlot is2 = last.get(i); - if (i != 0) { - sb.append("
"); - } - sb.append(is2.getText()); - } - - first.setText(sb.toString()); - - for (int i = 1; i < last.size(); i++) { - f.removeSlot(last.get(i)); - } - } - } - } - } - - public void addRule(RemoveInputsRule rule) { - rules.add(rule); - } - - public static class RemoveInputsRule { - - private Selector selector; - private int startingIndex; - private int endIndex; - - public RemoveInputsRule(Selector selector) { - this(selector, 0); - } - - public RemoveInputsRule(Selector selector, int startIndex) { - this(selector, startIndex, Integer.MAX_VALUE); - } - - public RemoveInputsRule(Selector selector, int startIndex, int endIndex) { - this.startingIndex = startIndex; - this.endIndex = endIndex; - this.selector = selector; - } - - public int getStartingIndex() { - return startingIndex; - } - - public int getEndIndex() { - return endIndex; - } - - public Selector getSelector() { - return selector; - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveSelfLoopsFilter.java --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/RemoveSelfLoopsFilter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filter; - -import com.sun.hotspot.igv.graph.*; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public class RemoveSelfLoopsFilter extends AbstractFilter { - - private String name; - - /** Creates a new instance of RemoveSelfLoops */ - public RemoveSelfLoopsFilter(String name) { - this.name = name; - } - - @Override - public String getName() { - return name; - } - - @Override - public void apply(Diagram d) { - - for (Figure f : d.getFigures()) { - - for (InputSlot is : f.getInputSlots()) { - - List toRemove = new ArrayList<>(); - for (Connection c : is.getConnections()) { - - if (c.getOutputSlot().getFigure() == f) { - toRemove.add(c); - } - } - - for (Connection c : toRemove) { - - c.remove(); - - OutputSlot os = c.getOutputSlot(); - if (os.getConnections().size() == 0) { - f.removeSlot(os); - } - - c.getInputSlot().setShortName("O"); - c.getInputSlot().setText("Self Loop"); - } - } - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/SplitFilter.java --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/SplitFilter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filter; - -import com.sun.hotspot.igv.graph.*; -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public class SplitFilter extends AbstractFilter { - - private String name; - private Selector selector; - private String propertyName; - - public SplitFilter(String name, Selector selector, String propertyName) { - this.name = name; - this.selector = selector; - this.propertyName = propertyName; - } - - @Override - public String getName() { - return name; - } - - @Override - public void apply(Diagram d) { - List
list = selector.selected(d); - - for (Figure f : list) { - - for (InputSlot is : f.getInputSlots()) { - for (Connection c : is.getConnections()) { - OutputSlot os = c.getOutputSlot(); - if (f.getSource().getSourceNodes().size() > 0) { - os.getSource().addSourceNodes(f.getSource()); - os.setAssociatedNode(f.getSource().getSourceNodes().get(0)); - os.setColor(f.getColor()); - } - - - String s = Figure.resolveString(propertyName, f.getProperties()); - if (s != null) { - os.setShortName(s); - } - - } - } - for (OutputSlot os : f.getOutputSlots()) { - for (Connection c : os.getConnections()) { - InputSlot is = c.getInputSlot(); - if (f.getSource().getSourceNodes().size() > 0) { - is.getSource().addSourceNodes(f.getSource()); - is.setAssociatedNode(f.getSource().getSourceNodes().get(0)); - is.setColor(f.getColor()); - } - - String s = Figure.resolveString(propertyName, f.getProperties()); - if (s != null) { - is.setShortName(s); - } - } - } - - d.removeFigure(f); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/UnconnectedSlotFilter.java --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/UnconnectedSlotFilter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filter; - -import com.sun.hotspot.igv.graph.*; -import java.util.ArrayList; -import java.util.List; - -/** - * Filter that hides slots with no connections. - */ -public class UnconnectedSlotFilter extends AbstractFilter { - - private final boolean removeInputs; - private final boolean removeOutputs; - - public UnconnectedSlotFilter(boolean inputs, boolean outputs) { - this.removeInputs = inputs; - this.removeOutputs = outputs; - } - - @Override - public String getName() { - return "Unconnected Slot Filter"; - } - - @Override - public void apply(Diagram d) { - if (!removeInputs && !removeOutputs) { - return; - } - - List
figures = d.getFigures(); - for (Figure f : figures) { - List remove = new ArrayList<>(); - if (removeInputs) { - for (InputSlot is : f.getInputSlots()) { - if (is.getConnections().isEmpty()) { - remove.add(is); - } - } - } - if (removeOutputs) { - for (OutputSlot os : f.getOutputSlots()) { - if (os.getConnections().isEmpty()) { - remove.add(os); - } - } - } - for (Slot s : remove) { - f.removeSlot(s); - } - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/helper.js --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/helper.js Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - - /** - * - * @author Thomas Wuerthinger - */ - -function colorize(property, regexp, color) { - var f = new ColorFilter(""); - f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), color)); - f.apply(graph); -} - -function remove(property, regexp) { - var f = new RemoveFilter(""); - f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)))); - f.apply(graph); -} - -function removeIncludingOrphans(property, regexp) { - var f = new RemoveFilter(""); - f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), true)); - f.apply(graph); -} - -function split(property, regexp, propertyName) { - if (propertyName == undefined) { - propertyName = graph.getNodeText(); - } - var f = new SplitFilter("", new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), propertyName); - f.apply(graph); -} - -function removeInputs(property, regexp, from, to) { - var f = new RemoveInputsFilter(""); - if(from == undefined && to == undefined) { - f.addRule(new RemoveInputsFilter.RemoveInputsRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)))); - } else if(to == undefined) { - f.addRule(new RemoveInputsFilter.RemoveInputsRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), from)); - } else { - f.addRule(new RemoveInputsFilter.RemoveInputsRule(new MatcherSelector(new Properties.RegexpPropertyMatcher(property, regexp)), from, to)); - } - f.apply(graph); -} - -function removeUnconnectedSlots(inputs, outputs) { - var f = new UnconnectedSlotFilter(inputs, outputs); - f.apply(graph); -} - -function colorizeGradient(property, min, max) { - var f = new GradientColorFilter(); - f.setPropertyName(property); - f.setMinValue(min); - f.setMaxValue(max); - f.apply(graph); -} - -function colorizeGradientWithMode(property, min, max, mode) { - var f = new GradientColorFilter(); - f.setPropertyName(property); - f.setMinValue(min); - f.setMaxValue(max); - f.setMode(mode); - f.apply(graph); -} - -function colorizeGradientCustom(property, min, max, mode, colors, fractions, nshades) { - var f = new GradientColorFilter(); - f.setPropertyName(property); - f.setMinValue(min); - f.setMaxValue(max); - f.setMode(mode); - f.setColors(colors); - f.setFractions(fractions); - f.setShadeCount(nshades); - f.apply(graph); -} - -var black = Color.black; -var blue = Color.blue; -var cyan = Color.cyan; -var darkGray = Color.darkGray; -var gray = Color.gray; -var green = Color.green; -var lightGray = Color.lightGray; -var magenta = Color.magenta; -var orange = Color.orange; -var pink = Color.pink -var red = Color.red; -var yellow = Color.yellow; -var white = Color.white; \ No newline at end of file diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Filter/src/com/sun/hotspot/igv/filter/layer.xml --- a/visualizer/Filter/src/com/sun/hotspot/igv/filter/layer.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/build.xml --- a/visualizer/FilterWindow/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project com.sun.hotspot.igv.filterwindow. - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/manifest.mf --- a/visualizer/FilterWindow/manifest.mf Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.sun.hotspot.igv.filterwindow -OpenIDE-Module-Layer: com/sun/hotspot/igv/filterwindow/layer.xml -OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/filterwindow/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/nbproject/build-impl.xml --- a/visualizer/FilterWindow/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ - - - - - - - - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/nbproject/genfiles.properties --- a/visualizer/FilterWindow/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=09ba2a87 -nbproject/build-impl.xml.script.CRC32=e4293f0e -nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.45.1 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/nbproject/project.properties --- a/visualizer/FilterWindow/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -javac.source=1.7 -javac.compilerargs=-Xlint -Xlint:-serial diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/nbproject/project.xml --- a/visualizer/FilterWindow/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - com.sun.hotspot.igv.filterwindow - - - - com.sun.hotspot.igv.data - - - - 1.0 - - - - com.sun.hotspot.igv.filter - - - - 1.0 - - - - com.sun.hotspot.igv.graph - - - - 1.0 - - - - com.sun.hotspot.igv.util - - - - 1.0 - - - - org.openide.actions - - - - 6.21.1 - - - - org.openide.dialogs - - - - 7.18.1 - - - - org.openide.explorer - - - - 6.34.1 - - - - org.openide.filesystems - - - - 7.46.1 - - - - org.openide.loaders - - - - 7.20.1 - - - - org.openide.nodes - - - - 7.20.1 - - - - org.openide.util - - - - 8.14.1 - - - - org.openide.util.lookup - - - - 8.6.1 - - - - org.openide.windows - - - - 6.39.1 - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/nbproject/suite.properties --- a/visualizer/FilterWindow/nbproject/suite.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -suite.dir=${basedir}/.. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/META-INF/services/com.sun.hotspot.igv.filter.FilterChainProvider --- a/visualizer/FilterWindow/src/META-INF/services/com.sun.hotspot.igv.filter.FilterChainProvider Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -com.sun.hotspot.igv.filterwindow.FilterChainProviderImplementation diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/Bundle.properties --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -OpenIDE-Module-Name=FilterWindow -CTL_FilterTopComponent=Filters -HINT_FilterTopComponent=Allows to choose active filters and modify them. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckListView.java --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckListView.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filterwindow; - -import javax.swing.JList; -import org.openide.explorer.view.ListView; -import org.openide.explorer.view.NodeListModel; - -/** - * - * @author Thomas Wuerthinger - */ -public class CheckListView extends ListView { - - @Override - public void showSelection(int[] indices) { - super.showSelection(indices); - } - - @Override - protected NodeListModel createModel() { - return new CheckNodeListModel(); - } - - @Override - protected JList createList() { - JList tmpList = super.createList(); - tmpList.setCellRenderer(new CheckRenderer(tmpList)); - return tmpList; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckNode.java --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckNode.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filterwindow; - -import com.sun.hotspot.igv.data.ChangedEvent; -import org.openide.nodes.AbstractNode; -import org.openide.nodes.Children; -import org.openide.util.Lookup; - -/** - * - * @author Thomas Wuerthinger - */ -public class CheckNode extends AbstractNode { - - private ChangedEvent selectionChangedEvent; - public boolean selected; - public boolean enabled; - - public CheckNode(Children c, Lookup lookup) { - super(c, lookup); - selectionChangedEvent = new ChangedEvent<>(this); - selected = false; - enabled = true; - } - - public ChangedEvent getSelectionChangedEvent() { - return selectionChangedEvent; - } - - public boolean isSelected() { - return selected; - } - - public void setSelected(boolean b) { - if (b != selected) { - selected = b; - selectionChangedEvent.fire(); - } - } - - public void setEnabled(boolean b) { - enabled = b; - } - - public boolean isEnabled() { - return enabled; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckNodeListModel.java --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckNodeListModel.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filterwindow; - -import org.openide.explorer.view.NodeListModel; -import org.openide.explorer.view.Visualizer; - -/** - * - * @author Thomas Wuerthinger - */ -public class CheckNodeListModel extends NodeListModel { - - public CheckNode getCheckNodeAt(int index) { - Object item = getElementAt(index); - if (item != null) { - return (CheckNode) Visualizer.findNode(item); - } - return null; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckRenderer.java --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/CheckRenderer.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filterwindow; - -import java.awt.*; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import javax.swing.JCheckBox; -import javax.swing.JList; -import javax.swing.ListCellRenderer; - -/** - * @author Thomas Wuerthinger - */ -public class CheckRenderer extends JCheckBox implements ListCellRenderer { - - private JList list; - private Color startBackground; - - public CheckRenderer(final JList list) { - this.list = list; - list.addMouseListener( - new MouseAdapter() { - - @Override - public void mouseClicked(MouseEvent e) { - int index = list.locationToIndex(e.getPoint()); - Point p2 = list.indexToLocation(index); - Rectangle r = new Rectangle(p2.x, p2.y, getPreferredSize().height, getPreferredSize().height); - if (r.contains(e.getPoint())) { - CheckNode node = ((CheckNodeListModel) list.getModel()).getCheckNodeAt(index); - node.setSelected(!node.isSelected()); - list.repaint(); - e.consume(); - } - } - }); - - this.setPreferredSize(new Dimension(getPreferredSize().width, getPreferredSize().height - 5)); - startBackground = this.getBackground(); - } - - @Override - public Component getListCellRendererComponent(final JList list, Object value, final int index, boolean isSelected, boolean cellHasFocus) { - setText(value.toString()); - CheckNode node = ((CheckNodeListModel) list.getModel()).getCheckNodeAt(index); - this.setSelected(node.isSelected()); - this.setEnabled(list.isEnabled()); - - if (isSelected && list.hasFocus()) { - this.setBackground(list.getSelectionBackground()); - this.setForeground(list.getSelectionForeground()); - } else if (isSelected) { - assert !list.hasFocus(); - this.setBackground(startBackground); - this.setForeground(list.getForeground()); - - } else { - this.setBackground(list.getBackground()); - this.setForeground(list.getForeground()); - } - return this; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterChainProviderImplementation.java --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterChainProviderImplementation.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filterwindow; - -import com.sun.hotspot.igv.filter.FilterChain; -import com.sun.hotspot.igv.filter.FilterChainProvider; - -/** - * - * @author Thomas Wuerthinger - */ -public class FilterChainProviderImplementation implements FilterChainProvider { - - @Override - public FilterChain getFilterChain() { - return FilterTopComponent.findInstance().getFilterChain(); - } - - @Override - public FilterChain getSequence() { - return FilterTopComponent.findInstance().getSequence(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterNode.java --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterNode.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filterwindow; - -import com.sun.hotspot.igv.data.ChangedListener; -import com.sun.hotspot.igv.filter.Filter; -import com.sun.hotspot.igv.filter.FilterChain; -import com.sun.hotspot.igv.filterwindow.actions.MoveFilterDownAction; -import com.sun.hotspot.igv.filterwindow.actions.MoveFilterUpAction; -import com.sun.hotspot.igv.filterwindow.actions.RemoveFilterAction; -import com.sun.hotspot.igv.util.PropertiesSheet; -import javax.swing.Action; -import org.openide.actions.OpenAction; -import org.openide.nodes.Children; -import org.openide.nodes.Sheet; -import org.openide.util.Lookup; -import org.openide.util.LookupEvent; -import org.openide.util.LookupListener; -import org.openide.util.Utilities; -import org.openide.util.lookup.AbstractLookup; -import org.openide.util.lookup.InstanceContent; - -/** - * - * @author Thomas Wuerthinger - */ -public class FilterNode extends CheckNode implements LookupListener, ChangedListener { - - private Filter filter; - private Lookup.Result result; - - public FilterNode(Filter filter) { - this(filter, new InstanceContent()); - } - - private FilterNode(Filter filter, InstanceContent content) { - super(Children.LEAF, new AbstractLookup(content)); - content.add(filter); - - content.add(filter.getEditor()); - this.filter = filter; - filter.getChangedEvent().addListener(new ChangedListener() { - - @Override - public void changed(Filter source) { - update(); - } - }); - - update(); - - Lookup.Template tpl = new Lookup.Template<>(FilterChain.class); - result = Utilities.actionsGlobalContext().lookup(tpl); - result.addLookupListener(this); - - FilterTopComponent.findInstance().getFilterSettingsChangedEvent().addListener(this); - resultChanged(null); - - setShortDescription("Double-click to open filter"); - } - - private void update() { - this.setDisplayName(filter.getName()); - } - - public Filter getFilter() { - return filter; - } - - @Override - protected Sheet createSheet() { - Sheet s = super.createSheet(); - PropertiesSheet.initializeSheet(getFilter().getProperties(), s); - return s; - } - - @Override - public Action[] getActions(boolean b) { - return new Action[]{(Action) OpenAction.findObject(OpenAction.class, true), (Action) MoveFilterUpAction.findObject(MoveFilterUpAction.class, true), (Action) MoveFilterDownAction.findObject(MoveFilterDownAction.class, true), (Action) RemoveFilterAction.findObject(RemoveFilterAction.class, true)}; - } - - @Override - public Action getPreferredAction() { - return OpenAction.get(OpenAction.class).createContextAwareInstance(Utilities.actionsGlobalContext()); - } - - @Override - public void resultChanged(LookupEvent lookupEvent) { - changed(FilterTopComponent.findInstance()); - } - - @Override - public void changed(FilterTopComponent source) { - setSelected(source.getFilterChain().containsFilter(filter)); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponent.form --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponent.form Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ - - -
- - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponent.java --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponent.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,670 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filterwindow; - -import com.sun.hotspot.igv.data.ChangedEvent; -import com.sun.hotspot.igv.data.ChangedListener; -import com.sun.hotspot.igv.filter.CustomFilter; -import com.sun.hotspot.igv.filter.Filter; -import com.sun.hotspot.igv.filter.FilterChain; -import com.sun.hotspot.igv.filter.FilterSetting; -import com.sun.hotspot.igv.filterwindow.actions.*; -import java.awt.BorderLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.*; -import java.util.*; -import javax.swing.JComboBox; -import javax.swing.UIManager; -import javax.swing.border.Border; -import org.openide.DialogDisplayer; -import org.openide.ErrorManager; -import org.openide.NotifyDescriptor; -import org.openide.awt.Toolbar; -import org.openide.awt.ToolbarPool; -import org.openide.explorer.ExplorerManager; -import org.openide.explorer.ExplorerUtils; -import org.openide.filesystems.FileLock; -import org.openide.filesystems.FileObject; -import org.openide.filesystems.FileUtil; -import org.openide.nodes.AbstractNode; -import org.openide.nodes.Children; -import org.openide.nodes.Node; -import org.openide.util.*; -import org.openide.util.actions.SystemAction; -import org.openide.windows.TopComponent; -import org.openide.windows.WindowManager; - -/** - * - * @author Thomas Wuerthinger - */ -public final class FilterTopComponent extends TopComponent implements LookupListener, ExplorerManager.Provider { - - private static FilterTopComponent instance; - public static final String FOLDER_ID = "Filters"; - public static final String AFTER_ID = "after"; - public static final String ENABLED_ID = "enabled"; - public static final String PREFERRED_ID = "FilterTopComponent"; - private CheckListView view; - private ExplorerManager manager; - private FilterChain filterChain; - private FilterChain sequence; - private Lookup.Result result; - private JComboBox comboBox; - private List filterSettings; - private FilterSetting customFilterSetting = new FilterSetting("-- Custom --"); - private ChangedEvent filterSettingsChangedEvent; - private ActionListener comboBoxActionListener = new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - comboBoxSelectionChanged(); - } - }; - - public ChangedEvent getFilterSettingsChangedEvent() { - return filterSettingsChangedEvent; - } - - public FilterChain getSequence() { - return sequence; - } - - public void updateSelection() { - Node[] nodes = this.getExplorerManager().getSelectedNodes(); - int[] arr = new int[nodes.length]; - for (int i = 0; i < nodes.length; i++) { - int index = sequence.getFilters().indexOf(((FilterNode) nodes[i]).getFilter()); - arr[i] = index; - } - view.showSelection(arr); - } - - private void comboBoxSelectionChanged() { - - Object o = comboBox.getSelectedItem(); - if (o == null) { - return; - } - assert o instanceof FilterSetting; - FilterSetting s = (FilterSetting) o; - - if (s != customFilterSetting) { - FilterChain chain = getFilterChain(); - chain.getChangedEvent().beginAtomic(); - List toRemove = new ArrayList<>(); - for (Filter f : chain.getFilters()) { - if (!s.containsFilter(f)) { - toRemove.add(f); - } - } - for (Filter f : toRemove) { - chain.removeFilter(f); - } - - for (Filter f : s.getFilters()) { - if (!chain.containsFilter(f)) { - chain.addFilter(f); - } - } - - chain.getChangedEvent().endAtomic(); - filterSettingsChangedEvent.fire(); - } else { - this.updateComboBoxSelection(); - } - - SystemAction.get(RemoveFilterSettingsAction.class).setEnabled(comboBox.getSelectedItem() != this.customFilterSetting); - SystemAction.get(SaveFilterSettingsAction.class).setEnabled(comboBox.getSelectedItem() == this.customFilterSetting); - } - - private void updateComboBox() { - comboBox.removeAllItems(); - comboBox.addItem(customFilterSetting); - for (FilterSetting s : filterSettings) { - comboBox.addItem(s); - } - - this.updateComboBoxSelection(); - } - - public void addFilterSetting() { - NotifyDescriptor.InputLine l = new NotifyDescriptor.InputLine("Name of the new profile:", "Filter Profile"); - if (DialogDisplayer.getDefault().notify(l) == NotifyDescriptor.OK_OPTION) { - String name = l.getInputText(); - - FilterSetting toRemove = null; - for (FilterSetting s : filterSettings) { - if (s.getName().equals(name)) { - NotifyDescriptor.Confirmation conf = new NotifyDescriptor.Confirmation("Filter profile \"" + name + "\" already exists, do you want to replace it?", "Filter"); - if (DialogDisplayer.getDefault().notify(conf) == NotifyDescriptor.YES_OPTION) { - toRemove = s; - break; - } else { - return; - } - } - } - - if (toRemove != null) { - filterSettings.remove(toRemove); - } - FilterSetting setting = createFilterSetting(name); - filterSettings.add(setting); - - // Sort alphabetically - Collections.sort(filterSettings, new Comparator() { - - @Override - public int compare(FilterSetting o1, FilterSetting o2) { - return o1.getName().compareTo(o2.getName()); - } - }); - - updateComboBox(); - } - } - - public boolean canRemoveFilterSetting() { - return comboBox.getSelectedItem() != customFilterSetting; - } - - public void removeFilterSetting() { - if (canRemoveFilterSetting()) { - Object o = comboBox.getSelectedItem(); - assert o instanceof FilterSetting; - FilterSetting f = (FilterSetting) o; - assert f != customFilterSetting; - assert filterSettings.contains(f); - NotifyDescriptor.Confirmation l = new NotifyDescriptor.Confirmation("Do you really want to remove filter profile \"" + f + "\"?", "Filter Profile"); - if (DialogDisplayer.getDefault().notify(l) == NotifyDescriptor.YES_OPTION) { - filterSettings.remove(f); - updateComboBox(); - } - } - } - - private FilterSetting createFilterSetting(String name) { - FilterSetting s = new FilterSetting(name); - FilterChain chain = this.getFilterChain(); - for (Filter f : chain.getFilters()) { - s.addFilter(f); - } - return s; - } - - private void updateComboBoxSelection() { - List filters = this.getFilterChain().getFilters(); - boolean found = false; - for (FilterSetting s : filterSettings) { - if (s.getFilterCount() == filters.size()) { - boolean ok = true; - for (Filter f : filters) { - if (!s.containsFilter(f)) { - ok = false; - } - } - - if (ok) { - if (comboBox.getSelectedItem() != s) { - comboBox.setSelectedItem(s); - } - found = true; - break; - } - } - } - - if (!found && comboBox.getSelectedItem() != customFilterSetting) { - comboBox.setSelectedItem(customFilterSetting); - } - } - - private class FilterChildren extends Children.Keys implements ChangedListener { - - private HashMap nodeHash = new HashMap<>(); - - @Override - protected Node[] createNodes(Filter filter) { - if (nodeHash.containsKey(filter)) { - return new Node[]{nodeHash.get(filter)}; - } - - FilterNode node = new FilterNode(filter); - node.getSelectionChangedEvent().addListener(this); - nodeHash.put(filter, node); - return new Node[]{node}; - } - - public FilterChildren() { - sequence.getChangedEvent().addListener(new ChangedListener() { - - @Override - public void changed(FilterChain source) { - addNotify(); - } - }); - - setBefore(false); - } - - @Override - protected void addNotify() { - setKeys(sequence.getFilters()); - updateSelection(); - } - - @Override - public void changed(CheckNode source) { - FilterNode node = (FilterNode) source; - Filter f = node.getFilter(); - FilterChain chain = getFilterChain(); - if (node.isSelected()) { - if (!chain.containsFilter(f)) { - chain.addFilter(f); - } - } else { - if (chain.containsFilter(f)) { - chain.removeFilter(f); - } - } - view.revalidate(); - view.repaint(); - updateComboBoxSelection(); - } - } - - public FilterChain getFilterChain() { - return filterChain; - } - - private FilterTopComponent() { - filterSettingsChangedEvent = new ChangedEvent<>(this); - initComponents(); - setName(NbBundle.getMessage(FilterTopComponent.class, "CTL_FilterTopComponent")); - setToolTipText(NbBundle.getMessage(FilterTopComponent.class, "HINT_FilterTopComponent")); - // setIcon(Utilities.loadImage(ICON_PATH, true)); - - sequence = new FilterChain(); - filterChain = new FilterChain(); - initFilters(); - manager = new ExplorerManager(); - manager.setRootContext(new AbstractNode(new FilterChildren())); - associateLookup(ExplorerUtils.createLookup(manager, getActionMap())); - view = new CheckListView(); - - ToolbarPool.getDefault().setPreferredIconSize(16); - Toolbar toolBar = new Toolbar(); - Border b = (Border) UIManager.get("Nb.Editor.Toolbar.border"); //NOI18N - toolBar.setBorder(b); - comboBox = new JComboBox(); - toolBar.add(comboBox); - this.add(toolBar, BorderLayout.NORTH); - toolBar.add(SaveFilterSettingsAction.get(SaveFilterSettingsAction.class)); - toolBar.add(RemoveFilterSettingsAction.get(RemoveFilterSettingsAction.class)); - toolBar.addSeparator(); - toolBar.add(NewFilterAction.get(NewFilterAction.class)); - toolBar.add(RemoveFilterAction.get(RemoveFilterAction.class).createContextAwareInstance(this.getLookup())); - toolBar.add(MoveFilterUpAction.get(MoveFilterUpAction.class).createContextAwareInstance(this.getLookup())); - toolBar.add(MoveFilterDownAction.get(MoveFilterDownAction.class).createContextAwareInstance(this.getLookup())); - this.add(view, BorderLayout.CENTER); - - filterSettings = new ArrayList<>(); - updateComboBox(); - - comboBox.addActionListener(comboBoxActionListener); - setChain(filterChain); - } - - public void newFilter() { - CustomFilter cf = new CustomFilter("My custom filter", ""); - if (cf.openInEditor()) { - sequence.addFilter(cf); - FileObject fo = getFileObject(cf); - FilterChangedListener listener = new FilterChangedListener(fo, cf); - listener.changed(cf); - cf.getChangedEvent().addListener(listener); - } - } - - public void removeFilter(Filter f) { - com.sun.hotspot.igv.filter.CustomFilter cf = (com.sun.hotspot.igv.filter.CustomFilter) f; - - sequence.removeFilter(cf); - try { - getFileObject(cf).delete(); - } catch (IOException ex) { - Exceptions.printStackTrace(ex); - } - - } - - private static class FilterChangedListener implements ChangedListener { - - private FileObject fileObject; - private CustomFilter filter; - - public FilterChangedListener(FileObject fo, CustomFilter cf) { - fileObject = fo; - filter = cf; - } - - @Override - public void changed(Filter source) { - try { - if (!fileObject.getName().equals(filter.getName())) { - FileLock lock = fileObject.lock(); - fileObject.move(lock, fileObject.getParent(), filter.getName(), ""); - lock.releaseLock(); - FileObject newFileObject = fileObject.getParent().getFileObject(filter.getName()); - fileObject = newFileObject; - } - - FileLock lock = fileObject.lock(); - OutputStream os = fileObject.getOutputStream(lock); - try (Writer w = new OutputStreamWriter(os)) { - String s = filter.getCode(); - w.write(s); - } - lock.releaseLock(); - - } catch (IOException ex) { - Exceptions.printStackTrace(ex); - } - } - } - - public void initFilters() { - FileObject folder = FileUtil.getConfigRoot().getFileObject(FOLDER_ID); - FileObject[] children = folder.getChildren(); - - List customFilters = new ArrayList<>(); - HashMap afterMap = new HashMap<>(); - Set enabledSet = new HashSet<>(); - HashMap map = new HashMap<>(); - - for (final FileObject fo : children) { - InputStream is = null; - - String code = ""; - FileLock lock = null; - try { - lock = fo.lock(); - is = fo.getInputStream(); - BufferedReader r = new BufferedReader(new InputStreamReader(is)); - String s; - StringBuilder sb = new StringBuilder(); - while ((s = r.readLine()) != null) { - sb.append(s); - sb.append("\n"); - } - code = sb.toString(); - } catch (FileNotFoundException ex) { - Exceptions.printStackTrace(ex); - } catch (IOException ex) { - Exceptions.printStackTrace(ex); - } finally { - try { - is.close(); - } catch (IOException ex) { - Exceptions.printStackTrace(ex); - } - lock.releaseLock(); - } - - String displayName = fo.getName(); - - - final CustomFilter cf = new CustomFilter(displayName, code); - map.put(displayName, cf); - - String after = (String) fo.getAttribute(AFTER_ID); - afterMap.put(cf, after); - - Boolean enabled = (Boolean) fo.getAttribute(ENABLED_ID); - if (enabled != null && (boolean) enabled) { - enabledSet.add(cf); - } - - cf.getChangedEvent().addListener(new FilterChangedListener(fo, cf)); - - customFilters.add(cf); - } - - for (int j = 0; j < customFilters.size(); j++) { - for (int i = 0; i < customFilters.size(); i++) { - List copiedList = new ArrayList<>(customFilters); - for (CustomFilter cf : copiedList) { - - String after = afterMap.get(cf); - - if (map.containsKey(after)) { - CustomFilter afterCf = map.get(after); - int index = customFilters.indexOf(afterCf); - int currentIndex = customFilters.indexOf(cf); - - if (currentIndex < index) { - customFilters.remove(currentIndex); - customFilters.add(index, cf); - } - } - } - } - } - - for (CustomFilter cf : customFilters) { - sequence.addFilter(cf); - if (enabledSet.contains(cf)) { - filterChain.addFilter(cf); - } - } - } - - /** This method is called from within the constructor to - * initialize the form. - * WARNING: Do NOT modify this code. The content of this method is - * always regenerated by the Form Editor. - */ - // //GEN-BEGIN:initComponents - private void initComponents() { - - setLayout(new java.awt.BorderLayout()); - - }// //GEN-END:initComponents - // Variables declaration - do not modify//GEN-BEGIN:variables - // End of variables declaration//GEN-END:variables - /** - * Gets default instance. Do not use directly: reserved for *.settings files only, - * i.e. deserialization routines; otherwise you could get a non-deserialized instance. - * To obtain the singleton instance, use {@link findInstance}. - */ - public static synchronized FilterTopComponent getDefault() { - if (instance == null) { - instance = new FilterTopComponent(); - } - return instance; - } - - /** - * Obtain the FilterTopComponent instance. Never call {@link #getDefault} directly! - */ - public static synchronized FilterTopComponent findInstance() { - TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID); - if (win == null) { - ErrorManager.getDefault().log(ErrorManager.WARNING, "Cannot find Filter component. It will not be located properly in the window system."); - return getDefault(); - } - if (win instanceof FilterTopComponent) { - return (FilterTopComponent) win; - } - ErrorManager.getDefault().log(ErrorManager.WARNING, "There seem to be multiple components with the '" + PREFERRED_ID + "' ID. That is a potential source of errors and unexpected behavior."); - return getDefault(); - } - - @Override - public int getPersistenceType() { - return TopComponent.PERSISTENCE_ALWAYS; - } - - @Override - protected String preferredID() { - return PREFERRED_ID; - } - - @Override - public ExplorerManager getExplorerManager() { - return manager; - } - - @Override - public void componentOpened() { - Lookup.Template tpl = new Lookup.Template<>(FilterChain.class); - result = Utilities.actionsGlobalContext().lookup(tpl); - result.addLookupListener(this); - } - - @Override - public void componentClosed() { - result.removeLookupListener(this); - result = null; - } - - @Override - public void resultChanged(LookupEvent lookupEvent) { - setChain(Utilities.actionsGlobalContext().lookup(FilterChain.class)); - } - - public void setChain(FilterChain chain) { - updateComboBoxSelection(); - } - - private FileObject getFileObject(CustomFilter cf) { - FileObject fo = FileUtil.getConfigRoot().getFileObject(FOLDER_ID + "/" + cf.getName()); - if (fo == null) { - try { - fo = FileUtil.getConfigRoot().getFileObject(FOLDER_ID).createData(cf.getName()); - } catch (IOException ex) { - Exceptions.printStackTrace(ex); - } - } - return fo; - } - - @Override - public boolean requestFocus(boolean temporary) { - view.requestFocus(); - return super.requestFocus(temporary); - } - - @Override - protected boolean requestFocusInWindow(boolean temporary) { - view.requestFocus(); - return super.requestFocusInWindow(temporary); - } - - @Override - public void requestActive() { - super.requestActive(); - view.requestFocus(); - } - - @Override - public void writeExternal(ObjectOutput out) throws IOException { - super.writeExternal(out); - - out.writeInt(filterSettings.size()); - for (FilterSetting f : filterSettings) { - out.writeUTF(f.getName()); - - out.writeInt(f.getFilterCount()); - for (Filter filter : f.getFilters()) { - CustomFilter cf = (CustomFilter) filter; - out.writeUTF(cf.getName()); - } - } - - CustomFilter prev = null; - for (Filter f : this.sequence.getFilters()) { - CustomFilter cf = (CustomFilter) f; - FileObject fo = getFileObject(cf); - if (getFilterChain().containsFilter(cf)) { - fo.setAttribute(ENABLED_ID, true); - } else { - fo.setAttribute(ENABLED_ID, false); - } - - if (prev == null) { - fo.setAttribute(AFTER_ID, null); - } else { - fo.setAttribute(AFTER_ID, prev.getName()); - } - - prev = cf; - } - } - - public CustomFilter findFilter(String name) { - for (Filter f : sequence.getFilters()) { - - CustomFilter cf = (CustomFilter) f; - if (cf.getName().equals(name)) { - return cf; - } - } - - return null; - } - - @Override - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - super.readExternal(in); - - int filterSettingsCount = in.readInt(); - for (int i = 0; i < filterSettingsCount; i++) { - String name = in.readUTF(); - FilterSetting s = new FilterSetting(name); - int filterCount = in.readInt(); - for (int j = 0; j < filterCount; j++) { - String filterName = in.readUTF(); - CustomFilter filter = findFilter(filterName); - if (filter != null) { - s.addFilter(filter); - } - } - - filterSettings.add(s); - } - updateComboBox(); - } - - final static class ResolvableHelper implements Serializable { - - private static final long serialVersionUID = 1L; - - public Object readResolve() { - return FilterTopComponent.getDefault(); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponentSettings.xml --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponentSettings.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponentWstcref.xml --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/FilterTopComponentWstcref.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/Bundle.properties --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -CTL_FilterAction=Filters -CTL_MoveFilterUpAction=Move upwards -CTL_MoveFilterDownAction=Move downwards -CTL_RemoveFilterAction=Remove -CTL_RemoveFilterSettingsAction=Remove filter setting -CTL_SaveFilterSettingsAction=Create filter profile... -CTL_NewFilterAction=New filter... diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/FilterAction.java --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/FilterAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filterwindow.actions; - -import com.sun.hotspot.igv.filterwindow.FilterTopComponent; -import java.awt.event.ActionEvent; -import javax.swing.AbstractAction; -import org.openide.util.NbBundle; -import org.openide.windows.TopComponent; - -/** - * - * @author Thomas Wuerthinger - */ -public class FilterAction extends AbstractAction { - - public FilterAction() { - super(NbBundle.getMessage(FilterAction.class, "CTL_FilterAction")); - } - - @Override - public void actionPerformed(ActionEvent evt) { - TopComponent win = FilterTopComponent.findInstance(); - win.open(); - win.requestActive(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/MoveFilterDownAction.java --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/MoveFilterDownAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filterwindow.actions; - -import com.sun.hotspot.igv.filter.Filter; -import com.sun.hotspot.igv.filterwindow.FilterTopComponent; -import javax.swing.Action; -import org.openide.nodes.Node; -import org.openide.util.HelpCtx; -import org.openide.util.NbBundle; -import org.openide.util.actions.CookieAction; - -/** - * - * @author Thomas Wuerthinger - */ -public final class MoveFilterDownAction extends CookieAction { - - @Override - protected void performAction(Node[] activatedNodes) { - for (Node n : activatedNodes) { - Filter c = n.getLookup().lookup(Filter.class); - FilterTopComponent.findInstance().getSequence().moveFilterDown(c); - } - } - - @Override - protected int mode() { - return CookieAction.MODE_EXACTLY_ONE; - } - - public MoveFilterDownAction() { - - putValue(Action.SHORT_DESCRIPTION, "Move selected filter downwards"); - } - - @Override - public String getName() { - return NbBundle.getMessage(MoveFilterUpAction.class, "CTL_MoveFilterDownAction"); - } - - @Override - protected Class[] cookieClasses() { - return new Class[]{ - Filter.class - }; - } - - @Override - protected String iconResource() { - return "com/sun/hotspot/igv/filterwindow/images/down.png"; - } - - @Override - protected void initialize() { - super.initialize(); - putValue("noIconInMenu", Boolean.TRUE); - } - - @Override - public HelpCtx getHelpCtx() { - return HelpCtx.DEFAULT_HELP; - } - - @Override - protected boolean asynchronous() { - return false; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/MoveFilterUpAction.java --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/MoveFilterUpAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filterwindow.actions; - -import com.sun.hotspot.igv.filter.Filter; -import com.sun.hotspot.igv.filterwindow.FilterTopComponent; -import javax.swing.Action; -import org.openide.nodes.Node; -import org.openide.util.HelpCtx; -import org.openide.util.NbBundle; -import org.openide.util.actions.CookieAction; - -/** - * - * @author Thomas Wuerthinger - */ -public final class MoveFilterUpAction extends CookieAction { - - @Override - protected void performAction(Node[] activatedNodes) { - for (Node n : activatedNodes) { - Filter c = n.getLookup().lookup(Filter.class); - FilterTopComponent.findInstance().getSequence().moveFilterUp(c); - } - } - - @Override - protected int mode() { - return CookieAction.MODE_EXACTLY_ONE; - } - - public MoveFilterUpAction() { - putValue(Action.SHORT_DESCRIPTION, "Move selected filter upwards"); - } - - @Override - public String getName() { - return NbBundle.getMessage(MoveFilterUpAction.class, "CTL_MoveFilterUpAction"); - } - - @Override - protected Class[] cookieClasses() { - return new Class[]{ - Filter.class - }; - } - - @Override - protected String iconResource() { - return "com/sun/hotspot/igv/filterwindow/images/up.png"; - } - - @Override - protected void initialize() { - super.initialize(); - putValue("noIconInMenu", Boolean.TRUE); - } - - @Override - public HelpCtx getHelpCtx() { - return HelpCtx.DEFAULT_HELP; - } - - @Override - protected boolean asynchronous() { - return false; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/NewFilterAction.java --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/NewFilterAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filterwindow.actions; - -import com.sun.hotspot.igv.filterwindow.FilterTopComponent; -import javax.swing.Action; -import org.openide.util.HelpCtx; -import org.openide.util.NbBundle; -import org.openide.util.actions.CallableSystemAction; - -/** - * - * @author Thomas Wuerthinger - */ -public final class NewFilterAction extends CallableSystemAction { - - public NewFilterAction() { - putValue(Action.SHORT_DESCRIPTION, "Create new filter"); - } - - @Override - public void performAction() { - FilterTopComponent.findInstance().newFilter(); - } - - @Override - public String getName() { - return NbBundle.getMessage(SaveFilterSettingsAction.class, "CTL_NewFilterAction"); - } - - @Override - protected void initialize() { - super.initialize(); - } - - @Override - public HelpCtx getHelpCtx() { - return HelpCtx.DEFAULT_HELP; - } - - @Override - protected boolean asynchronous() { - return false; - } - - @Override - protected String iconResource() { - return "com/sun/hotspot/igv/filterwindow/images/plus.png"; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/RemoveFilterAction.java --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/RemoveFilterAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filterwindow.actions; - -import com.sun.hotspot.igv.filter.Filter; -import com.sun.hotspot.igv.filterwindow.FilterTopComponent; -import javax.swing.Action; -import javax.swing.JOptionPane; -import org.openide.nodes.Node; -import org.openide.util.HelpCtx; -import org.openide.util.NbBundle; -import org.openide.util.actions.CookieAction; -import org.openide.windows.WindowManager; - -/** - * - * @author Thomas Wuerthinger - */ -public final class RemoveFilterAction extends CookieAction { - - @Override - protected void performAction(Node[] activatedNodes) { - Object[] options = {"Yes", - "No", - "Cancel" - }; - int n = JOptionPane.showOptionDialog(WindowManager.getDefault().getMainWindow(), - "Do you really want to delete " + activatedNodes.length + " filter(s)?", "Delete Filters", - JOptionPane.YES_NO_CANCEL_OPTION, - JOptionPane.QUESTION_MESSAGE, - null, - options, - options[2]); - - if (n == JOptionPane.YES_OPTION) { - for (int i = 0; i < activatedNodes.length; i++) { - FilterTopComponent.findInstance().removeFilter(activatedNodes[i].getLookup().lookup(Filter.class)); - } - } - } - - @Override - protected int mode() { - return CookieAction.MODE_ALL; - } - - @Override - public String getName() { - return NbBundle.getMessage(RemoveFilterAction.class, "CTL_RemoveFilterAction"); - } - - public RemoveFilterAction() { - putValue(Action.SHORT_DESCRIPTION, "Remove selected filter"); - } - - @Override - protected Class[] cookieClasses() { - return new Class[]{ - Filter.class - }; - } - - @Override - protected void initialize() { - super.initialize(); - putValue("noIconInMenu", Boolean.TRUE); - } - - @Override - protected String iconResource() { - return "com/sun/hotspot/igv/filterwindow/images/minus.png"; - } - - @Override - public HelpCtx getHelpCtx() { - return HelpCtx.DEFAULT_HELP; - } - - @Override - protected boolean asynchronous() { - return false; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/RemoveFilterSettingsAction.java --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/RemoveFilterSettingsAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filterwindow.actions; - -import com.sun.hotspot.igv.filterwindow.FilterTopComponent; -import javax.swing.Action; -import org.openide.util.HelpCtx; -import org.openide.util.NbBundle; -import org.openide.util.actions.CallableSystemAction; - -/** - * - * @author Thomas Wuerthinger - */ -public final class RemoveFilterSettingsAction extends CallableSystemAction { - - @Override - public void performAction() { - FilterTopComponent.findInstance().removeFilterSetting(); - } - - @Override - public String getName() { - return NbBundle.getMessage(RemoveFilterSettingsAction.class, "CTL_RemoveFilterSettingsAction"); - } - - public RemoveFilterSettingsAction() { - putValue(Action.SHORT_DESCRIPTION, "Delete current filter profile"); - } - - @Override - protected void initialize() { - super.initialize(); - } - - @Override - public HelpCtx getHelpCtx() { - return HelpCtx.DEFAULT_HELP; - } - - @Override - protected boolean asynchronous() { - return false; - } - - @Override - protected String iconResource() { - return "com/sun/hotspot/igv/filterwindow/images/delete.png"; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/SaveFilterSettingsAction.java --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/actions/SaveFilterSettingsAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.filterwindow.actions; - -import com.sun.hotspot.igv.filterwindow.FilterTopComponent; -import javax.swing.Action; -import org.openide.util.HelpCtx; -import org.openide.util.NbBundle; -import org.openide.util.actions.CallableSystemAction; - -/** - * - * @author Thomas Wuerthinger - */ -public final class SaveFilterSettingsAction extends CallableSystemAction { - - @Override - public void performAction() { - FilterTopComponent.findInstance().addFilterSetting(); - } - - @Override - public String getName() { - return NbBundle.getMessage(SaveFilterSettingsAction.class, "CTL_SaveFilterSettingsAction"); - } - - @Override - protected void initialize() { - super.initialize(); - } - - public SaveFilterSettingsAction() { - putValue(Action.SHORT_DESCRIPTION, "Save filter configuration as profile..."); - } - - @Override - public HelpCtx getHelpCtx() { - return HelpCtx.DEFAULT_HELP; - } - - @Override - protected boolean asynchronous() { - return false; - } - - @Override - protected String iconResource() { - return "com/sun/hotspot/igv/filterwindow/images/add.png"; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/customRightTopWsmode.xml --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/customRightTopWsmode.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/add.png Binary file visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/add.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/delete.png Binary file visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/delete.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/down.png Binary file visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/down.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/minus.png Binary file visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/minus.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/plus.png Binary file visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/plus.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/up.png Binary file visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/images/up.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/layer.xml --- a/visualizer/FilterWindow/src/com/sun/hotspot/igv/filterwindow/layer.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/build.xml --- a/visualizer/Graal/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project com.sun.hotspot.igv.graal. - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/manifest.mf --- a/visualizer/Graal/manifest.mf Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.sun.hotspot.igv.graal -OpenIDE-Module-Layer: com/sun/hotspot/igv/graal/layer.xml -OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/graal/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/nbproject/build-impl.xml --- a/visualizer/Graal/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ - - - - - - - - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/nbproject/genfiles.properties --- a/visualizer/Graal/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -build.xml.data.CRC32=79002a09 -build.xml.script.CRC32=3534d355 -build.xml.stylesheet.CRC32=a56c6a5b@2.47.1 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=79002a09 -nbproject/build-impl.xml.script.CRC32=2867f2d5 -nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/nbproject/project.properties --- a/visualizer/Graal/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -javac.source=1.7 -javac.compilerargs=-Xlint -Xlint:-serial diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/nbproject/project.xml --- a/visualizer/Graal/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - com.sun.hotspot.igv.graal - - - - com.sun.hotspot.igv.data - - - - 1.0 - - - - com.sun.hotspot.igv.filter - - - - 1.0 - - - - com.sun.hotspot.igv.graph - - - - 1.0 - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/nbproject/suite.properties --- a/visualizer/Graal/nbproject/suite.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -suite.dir=${basedir}/.. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/src/com/sun/hotspot/igv/graal/Bundle.properties --- a/visualizer/Graal/src/com/sun/hotspot/igv/graal/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -OpenIDE-Module-Name=GraalCompilerSupport diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalCFGFilter.java --- a/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalCFGFilter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.graal.filters; - -import com.sun.hotspot.igv.data.Properties; -import com.sun.hotspot.igv.filter.AbstractFilter; -import com.sun.hotspot.igv.graph.Connection; -import com.sun.hotspot.igv.graph.Diagram; -import com.sun.hotspot.igv.graph.Figure; -import com.sun.hotspot.igv.graph.InputSlot; -import java.util.HashSet; -import java.util.Set; - -public class GraalCFGFilter extends AbstractFilter { - - @Override - public String getName() { - return "Graal CFG Filter"; - } - - @Override - public void apply(Diagram d) { - Set
figuresToRemove = new HashSet<>(); - Set connectionsToRemove = new HashSet<>(); - for (Figure f : d.getFigures()) { - final String prop = f.getProperties().get("probability"); - - if (prop == null) { - figuresToRemove.add(f); - } - } - d.removeAllFigures(figuresToRemove); - - for (Figure f : d.getFigures()) { - Properties p = f.getProperties(); - int predCount = Integer.parseInt(p.get("predecessorCount")); - for (InputSlot is : f.getInputSlots()) { - if (is.getPosition() >= predCount && !"EndNode".equals(is.getProperties().get("class"))) { - for (Connection c : is.getConnections()) { - if (!"EndNode".equals(c.getOutputSlot().getFigure().getProperties().get("class"))) { - connectionsToRemove.add(c); - } - } - } - } - } - - for (Connection c : connectionsToRemove) { - c.remove(); - System.out.println("rm " + c); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalColoringFilter.java --- a/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalColoringFilter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.graal.filters; - -import com.sun.hotspot.igv.data.Properties; -import com.sun.hotspot.igv.filter.AbstractFilter; -import com.sun.hotspot.igv.graph.Diagram; -import com.sun.hotspot.igv.graph.Figure; -import java.awt.Color; -import java.util.List; - -public class GraalColoringFilter extends AbstractFilter { - - private String colorName; - - public GraalColoringFilter(String colorName) { - this.colorName = colorName; - } - - @Override - public String getName() { - return "Graal Coloring Filter (" + colorName + ")"; - } - - @Override - public void apply(Diagram d) { - List
figures = d.getFigures(); - int colors = 0; - for (Figure f : figures) { - Properties p = f.getProperties(); - final String prop = p.get(colorName + "Color"); - if (prop == null) { - continue; - } - try { - int color = Integer.parseInt(prop); - if (color > colors) { - colors = color; - } - } catch (NumberFormatException nfe) { - // nothing to do - } - } - colors++; - for (Figure f : figures) { - Properties p = f.getProperties(); - final String prop = p.get(colorName + "Color"); - if (prop == null) { - continue; - } - try { - int color = Integer.parseInt(prop); - Color c = Color.getHSBColor((float) color / colors, 1.0f, 0.7f); - f.setColor(c); - } catch (NumberFormatException nfe) { - // nothing to do - } - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java --- a/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.graal.filters; - -import com.sun.hotspot.igv.data.Properties; -import com.sun.hotspot.igv.filter.AbstractFilter; -import com.sun.hotspot.igv.graph.Connection; -import com.sun.hotspot.igv.graph.Connection.ConnectionStyle; -import com.sun.hotspot.igv.graph.Diagram; -import com.sun.hotspot.igv.graph.Figure; -import com.sun.hotspot.igv.graph.InputSlot; -import java.awt.Color; -import java.util.List; - -/** - * Filter that colors usage and successor edges differently. - * - * @author Peter Hofer - */ -public class GraalEdgeColorFilter extends AbstractFilter { - - private Color successorColor = Color.BLUE; - private Color usageColor = Color.RED; - private Color memoryColor = Color.GREEN; - - public GraalEdgeColorFilter() { - } - - @Override - public String getName() { - return "Graal Edge Color Filter"; - } - - @Override - public void apply(Diagram d) { - List
figures = d.getFigures(); - for (Figure f : figures) { - Properties p = f.getProperties(); - int predCount; - if (p.get("predecessorCount") != null) { - predCount = Integer.parseInt(p.get("predecessorCount")); - } else { - predCount = 0; - } - for (InputSlot is : f.getInputSlots()) { - Color color; - ConnectionStyle style = ConnectionStyle.NORMAL; - if (is.getPosition() < predCount) { - color = successorColor; - style = ConnectionStyle.BOLD; - } else { - color = usageColor; - } - - is.setColor(color); - for (Connection c : is.getConnections()) { - if (c.getLabel() == null || !c.getLabel().endsWith("#NDF")) { - c.setColor(color); - if (c.getStyle() != ConnectionStyle.DASHED) { - c.setStyle(style); - } - } else if ("EndNode".equals(c.getOutputSlot().getFigure().getProperties().get("class")) - || "EndNode".equals(c.getOutputSlot().getProperties().get("class"))) { - c.setColor(successorColor); - c.setStyle(ConnectionStyle.BOLD); - } - } - } - } - } - - public Color getUsageColor() { - return usageColor; - } - - public void setUsageColor(Color usageColor) { - this.usageColor = usageColor; - } - - public void setMemoryColor(Color memoryColor) { - this.memoryColor = memoryColor; - } - - public Color getMemoryColor() { - return memoryColor; - } - - public Color getSuccessorColor() { - return successorColor; - } - - public void setSuccessorColor(Color successorColor) { - this.successorColor = successorColor; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/beginend.filter --- a/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/beginend.filter Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -var f = new CombineFilter("Combine Filter"); -f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("class", ".*"), new Properties.RegexpPropertyMatcher("class", "BeginNode"), false, "shortName")); -f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("class", "EndNode"), new Properties.RegexpPropertyMatcher("class", ".*"), true, "shortName")); -f.apply(graph); diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/callgraph.filter --- a/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/callgraph.filter Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -colorize("name", ".*", yellow); -colorize("name", ".*", pink); -colorize("leaf", "1", lightGray); -colorize("cutoff", "1", red); diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/cfg.filter --- a/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/cfg.filter Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -var f = new com.sun.hotspot.igv.graal.filters.GraalCFGFilter(); -f.apply(graph); diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/color.filter --- a/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/color.filter Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -colorize("name", ".*", white); -colorize("name", "Begin|EndNode|LoopBegin|LoopEnd|LoopExit|Return", orange); -colorize("name", "Phi.*|ValueProxy", magenta); -colorize("name", "FrameState@.*", new java.awt.Color(0.5, 0.8, 1.0)); -colorize("name", "If|Merge", pink); -colorize("name", "const.*", new java.awt.Color(0.7, 0.7, 0.7)); -colorize("name", "Local", new java.awt.Color(0.85, 0.85, 0.85)); -colorize("name", "\\+|-|\\*|/|&|\\||<<|>>|>>>", cyan); -colorize("name", "Comp .*", yellow); -colorize("name", "Virtual.*", green); - -colorize("notInOwnBlock", "true", red); \ No newline at end of file diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/edgeColor.filter --- a/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/edgeColor.filter Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -var f = new com.sun.hotspot.igv.graal.filters.GraalEdgeColorFilter(); -f.setUsageColor(blue); -f.setSuccessorColor(red); -f.apply(graph); diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/framestatelocks.filter --- a/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/framestatelocks.filter Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -colorize("class", "FrameState", red); -colorize("locks", "", gray); \ No newline at end of file diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/noframestate.filter --- a/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/noframestate.filter Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -remove("class", "FrameState"); \ No newline at end of file diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/probability.filter --- a/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/probability.filter Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -colorizeGradientWithMode("probability", 0, 500, "logarithmic"); - -// more parameters: colorizeGradientCustom("probability", 0, 500, "logarithmic", [blue, yellow, red], [0, 0.5, 1], 16); diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/slots.filter --- a/visualizer/Graal/src/com/sun/hotspot/igv/graal/filters/slots.filter Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -removeUnconnectedSlots(true, true); diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graal/src/com/sun/hotspot/igv/graal/layer.xml --- a/visualizer/Graal/src/com/sun/hotspot/igv/graal/layer.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/build.xml --- a/visualizer/Graph/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project com.sun.hotspot.igv.graph. - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/manifest.mf --- a/visualizer/Graph/manifest.mf Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.sun.hotspot.igv.graph -OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/graph/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/nbproject/build-impl.xml --- a/visualizer/Graph/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/nbproject/genfiles.properties --- a/visualizer/Graph/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -build.xml.data.CRC32=b2bc2f02 -build.xml.script.CRC32=486d5dab -build.xml.stylesheet.CRC32=79c3b980 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=b2bc2f02 -nbproject/build-impl.xml.script.CRC32=17fa0f49 -nbproject/build-impl.xml.stylesheet.CRC32=deb65f65 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/nbproject/platform.properties --- a/visualizer/Graph/nbproject/platform.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -# Deprecated since 5.0u1; for compatibility with 5.0: -disabled.clusters=\ - apisupport1,\ - harness,\ - ide8,\ - java1,\ - nb6.0,\ - profiler2 -disabled.modules=\ - org.netbeans.core.execution,\ - org.netbeans.core.multiview,\ - org.netbeans.core.output2,\ - org.netbeans.modules.applemenu,\ - org.netbeans.modules.autoupdate.services,\ - org.netbeans.modules.autoupdate.ui,\ - org.netbeans.modules.core.kit,\ - org.netbeans.modules.favorites,\ - org.netbeans.modules.javahelp,\ - org.netbeans.modules.masterfs,\ - org.netbeans.modules.options.keymap,\ - org.netbeans.modules.sendopts,\ - org.netbeans.modules.templates,\ - org.openide.compat,\ - org.openide.execution,\ - org.openide.util.enumerations -enabled.clusters=\ - platform7 -nbjdk.active=JDK_1.6 -nbplatform.active=default diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/nbproject/project.properties --- a/visualizer/Graph/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -javac.source=1.7 -javac.compilerargs=-Xlint -Xlint:-serial diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/nbproject/project.xml --- a/visualizer/Graph/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - com.sun.hotspot.igv.graph - - - - com.sun.hotspot.igv.data - - - - 1.0 - - - - com.sun.hotspot.igv.layout - - - - 1.0 - - - - - com.sun.hotspot.igv.graph - com.sun.hotspot.igv.graph.services - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/nbproject/suite.properties --- a/visualizer/Graph/nbproject/suite.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -suite.dir=${basedir}/.. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/src/com/sun/hotspot/igv/graph/AndSelector.java --- a/visualizer/Graph/src/com/sun/hotspot/igv/graph/AndSelector.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.graph; - -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public class AndSelector implements Selector { - - private Selector selector1; - private Selector selector2; - - public AndSelector(Selector s1, Selector s2) { - this.selector1 = s1; - this.selector2 = s2; - } - - @Override - public List
selected(Diagram d) { - List
l1 = selector1.selected(d); - List
l2 = selector2.selected(d); - List
result = new ArrayList<>(); - for (Figure f : l2) { - if (l1.contains(f)) { - result.add(f); - } - } - return result; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/src/com/sun/hotspot/igv/graph/Bundle.properties --- a/visualizer/Graph/src/com/sun/hotspot/igv/graph/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -OpenIDE-Module-Name=Graph diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/src/com/sun/hotspot/igv/graph/Connection.java --- a/visualizer/Graph/src/com/sun/hotspot/igv/graph/Connection.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.graph; - -import com.sun.hotspot.igv.data.Source; -import com.sun.hotspot.igv.layout.Link; -import com.sun.hotspot.igv.layout.Port; -import java.awt.Color; -import java.awt.Point; -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public class Connection implements Source.Provider, Link { - - @Override - public boolean isVIP() { - return style == ConnectionStyle.BOLD; - } - - public enum ConnectionStyle { - - NORMAL, - DASHED, - BOLD - } - private InputSlot inputSlot; - private OutputSlot outputSlot; - private Source source; - private Color color; - private ConnectionStyle style; - private List controlPoints; - private String label; - - protected Connection(InputSlot inputSlot, OutputSlot outputSlot, String label) { - this.inputSlot = inputSlot; - this.outputSlot = outputSlot; - this.label = label; - this.inputSlot.connections.add(this); - this.outputSlot.connections.add(this); - controlPoints = new ArrayList<>(); - Figure sourceFigure = this.outputSlot.getFigure(); - Figure destFigure = this.inputSlot.getFigure(); - sourceFigure.addSuccessor(destFigure); - destFigure.addPredecessor(sourceFigure); - source = new Source(); - - this.color = Color.BLACK; - this.style = ConnectionStyle.NORMAL; - } - - public InputSlot getInputSlot() { - return inputSlot; - } - - public OutputSlot getOutputSlot() { - return outputSlot; - } - - public Color getColor() { - return color; - } - - public ConnectionStyle getStyle() { - return style; - } - - public void setColor(Color c) { - color = c; - } - - public void setStyle(ConnectionStyle s) { - style = s; - } - - @Override - public Source getSource() { - return source; - } - - public String getLabel() { - return label; - } - - public void remove() { - inputSlot.getFigure().removePredecessor(outputSlot.getFigure()); - inputSlot.connections.remove(this); - outputSlot.getFigure().removeSuccessor(inputSlot.getFigure()); - outputSlot.connections.remove(this); - } - - public String getToolTipText() { - StringBuilder builder = new StringBuilder(); - if (label != null) { - builder.append(label).append(": from "); - } else { - builder.append("From "); - } - builder.append(getOutputSlot().getFigure().getSource().getSourceNodes().get(0).getId()); - builder.append(" to "); - builder.append(getInputSlot().getFigure().getSource().getSourceNodes().get(0).getId()); - return builder.toString(); - } - - @Override - public String toString() { - return "Connection('" + label + "', " + getFrom().getVertex() + " to " + getTo().getVertex() + ")"; - } - - @Override - public Port getFrom() { - return outputSlot; - } - - @Override - public Port getTo() { - return inputSlot; - } - - @Override - public List getControlPoints() { - return controlPoints; - } - - @Override - public void setControlPoints(List list) { - controlPoints = list; - } -} - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java --- a/visualizer/Graph/src/com/sun/hotspot/igv/graph/Diagram.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,283 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.graph; - -import com.sun.hotspot.igv.data.InputEdge; -import com.sun.hotspot.igv.data.InputGraph; -import com.sun.hotspot.igv.data.InputNode; -import com.sun.hotspot.igv.data.Properties; -import com.sun.hotspot.igv.data.Properties.StringPropertyMatcher; -import java.awt.Font; -import java.util.*; - -/** - * - * @author Thomas Wuerthinger - */ -public class Diagram { - - private List
figures; - private InputGraph graph; - private int curId; - private String nodeText; - private Font font; - private Font slotFont; - - public Font getFont() { - return font; - } - - public Font getSlotFont() { - return slotFont; - } - - private Diagram() { - figures = new ArrayList<>(); - this.nodeText = ""; - this.font = new Font("Arial", Font.PLAIN, 13); - this.slotFont = new Font("Arial", Font.PLAIN, 10); - } - - public String getNodeText() { - return nodeText; - } - - public Diagram getNext() { - return Diagram.createDiagram(graph.getNext(), nodeText); - } - - public Diagram getPrev() { - return Diagram.createDiagram(graph.getPrev(), nodeText); - } - - public List
getFigures() { - return Collections.unmodifiableList(figures); - } - - public Figure createFigure() { - Figure f = new Figure(this, curId); - curId++; - this.figures.add(f); - return f; - } - - public Connection createConnection(InputSlot inputSlot, OutputSlot outputSlot, String label) { - assert inputSlot.getFigure().getDiagram() == this; - assert outputSlot.getFigure().getDiagram() == this; - return new Connection(inputSlot, outputSlot, label); - } - - public Map> calcSourceToFigureRelation() { - Map> map = new HashMap<>(); - - for(InputNode node : this.getGraph().getNodes()) { - map.put(node, new HashSet
()); - } - - for(Figure f : this.getFigures()) { - for(InputNode node : f.getSource().getSourceNodes()) { - map.get(node).add(f); - } - } - - return map; - } - - public static Diagram createDiagram(InputGraph graph, String nodeText) { - if (graph == null) { - return null; - } - - Diagram d = new Diagram(); - d.graph = graph; - d.nodeText = nodeText; - - Collection nodes = graph.getNodes(); - Hashtable figureHash = new Hashtable<>(); - for (InputNode n : nodes) { - Figure f = d.createFigure(); - f.getSource().addSourceNode(n); - f.getProperties().add(n.getProperties()); - figureHash.put(n.getId(), f); - } - - for (InputEdge e : graph.getEdges()) { - - int from = e.getFrom(); - int to = e.getTo(); - Figure fromFigure = figureHash.get(from); - Figure toFigure = figureHash.get(to); - assert fromFigure != null && toFigure != null; - - if(fromFigure == null || toFigure == null) continue; - - int fromIndex = e.getFromIndex(); - while (fromFigure.getOutputSlots().size() <= fromIndex) { - fromFigure.createOutputSlot(); - } - OutputSlot outputSlot = fromFigure.getOutputSlots().get(fromIndex); - - int toIndex = e.getToIndex(); - while (toFigure.getInputSlots().size() <= toIndex) { - toFigure.createInputSlot(); - } - InputSlot inputSlot = toFigure.getInputSlots().get(toIndex); - - Connection c = d.createConnection(inputSlot, outputSlot, e.getLabel()); - - if (e.getState() == InputEdge.State.NEW) { - c.setStyle(Connection.ConnectionStyle.BOLD); - } else if (e.getState() == InputEdge.State.DELETED) { - c.setStyle(Connection.ConnectionStyle.DASHED); - } - } - - - return d; - } - - public void removeAllFigures(Set
figuresToRemove) { - for (Figure f : figuresToRemove) { - freeFigure(f); - } - - ArrayList
newFigures = new ArrayList<>(); - for (Figure f : this.figures) { - if (!figuresToRemove.contains(f)) { - newFigures.add(f); - } - } - figures = newFigures; - } - - private void freeFigure(Figure succ) { - - List inputSlots = new ArrayList<>(succ.getInputSlots()); - for (InputSlot s : inputSlots) { - succ.removeInputSlot(s); - } - - List outputSlots = new ArrayList<>(succ.getOutputSlots()); - for (OutputSlot s : outputSlots) { - succ.removeOutputSlot(s); - } - - assert succ.getInputSlots().size() == 0; - assert succ.getOutputSlots().size() == 0; - assert succ.getPredecessors().size() == 0; - assert succ.getSuccessors().size() == 0; - - } - - public void removeFigure(Figure succ) { - - assert this.figures.contains(succ); - freeFigure(succ); - this.figures.remove(succ); - } - - public String getName() { - return graph.getName(); - } - - public InputGraph getGraph() { - return graph; - } - - public Set getConnections() { - - Set connections = new HashSet<>(); - for (Figure f : figures) { - - for (InputSlot s : f.getInputSlots()) { - connections.addAll(s.getConnections()); - } - } - - return connections; - } - - public Figure getRootFigure() { - Properties.PropertySelector
selector = new Properties.PropertySelector<>(figures); - Figure root = selector.selectSingle(new StringPropertyMatcher("name", "Root")); - if (root == null) { - root = selector.selectSingle(new StringPropertyMatcher("name", "Start")); - } - if (root == null) { - List
rootFigures = getRootFigures(); - if (rootFigures.size() > 0) { - root = rootFigures.get(0); - } else if (figures.size() > 0) { - root = figures.get(0); - } - } - - return root; - } - - public void printStatistics() { - System.out.println("============================================================="); - System.out.println("Diagram statistics"); - - List
tmpFigures = getFigures(); - Set connections = getConnections(); - - System.out.println("Number of figures: " + tmpFigures.size()); - System.out.println("Number of connections: " + connections.size()); - - List
figuresSorted = new ArrayList<>(tmpFigures); - Collections.sort(figuresSorted, new Comparator
() { - - @Override - public int compare(Figure a, Figure b) { - return b.getPredecessors().size() + b.getSuccessors().size() - a.getPredecessors().size() - a.getSuccessors().size(); - } - }); - - final int COUNT = 10; - int z = 0; - for (Figure f : figuresSorted) { - - z++; - int sum = f.getPredecessors().size() + f.getSuccessors().size(); - System.out.println("#" + z + ": " + f + ", predCount=" + f.getPredecessors().size() + " succCount=" + f.getSuccessors().size()); - if (sum < COUNT) { - break; - } - - } - - System.out.println("============================================================="); - } - - public List
getRootFigures() { - ArrayList
rootFigures = new ArrayList<>(); - for (Figure f : figures) { - if (f.getPredecessors().size() == 0) { - rootFigures.add(f); - } - } - return rootFigures; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/src/com/sun/hotspot/igv/graph/Figure.java --- a/visualizer/Graph/src/com/sun/hotspot/igv/graph/Figure.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,355 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.graph; - -import com.sun.hotspot.igv.data.InputNode; -import com.sun.hotspot.igv.data.Properties; -import com.sun.hotspot.igv.data.Source; -import com.sun.hotspot.igv.layout.Vertex; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.util.List; -import java.util.*; - -/** - * - * @author Thomas Wuerthinger - */ -public class Figure extends Properties.Entity implements Source.Provider, Vertex { - - public static final int INSET = 12; - public static int SLOT_WIDTH = 12; - public static final int OVERLAPPING = 6; - public static final int SLOT_START = 4; - public static final int SLOT_OFFSET = 8; - public static final boolean VERTICAL_LAYOUT = true; - protected List inputSlots; - protected List outputSlots; - private Source source; - private Diagram diagram; - private Point position; - private List
predecessors; - private List
successors; - private Color color; - private int id; - private String idString; - private String[] lines; - private int heightCash = -1; - private int widthCash = -1; - - public int getHeight() { - if (heightCash == -1) { - BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); - Graphics g = image.getGraphics(); - g.setFont(diagram.getFont().deriveFont(Font.BOLD)); - FontMetrics metrics = g.getFontMetrics(); - String nodeText = diagram.getNodeText(); - heightCash = nodeText.split("\n").length * metrics.getHeight() + INSET; - } - return heightCash; - } - - public static List getAllBefore(List inputList, T tIn) { - List result = new ArrayList<>(); - for(T t : inputList) { - if(t.equals(tIn)) { - break; - } - result.add(t); - } - return result; - } - - public static int getSlotsWidth(Collection slots) { - int result = Figure.SLOT_OFFSET; - for(Slot s : slots) { - result += s.getWidth() + Figure.SLOT_OFFSET; - } - return result; - } - - public int getWidth() { - if (widthCash == -1) { - int max = 0; - BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); - Graphics g = image.getGraphics(); - g.setFont(diagram.getFont().deriveFont(Font.BOLD)); - FontMetrics metrics = g.getFontMetrics(); - for (String s : getLines()) { - int cur = metrics.stringWidth(s); - if (cur > max) { - max = cur; - } - } - widthCash = max + INSET; - widthCash = Math.max(widthCash, Figure.getSlotsWidth(inputSlots)); - widthCash = Math.max(widthCash, Figure.getSlotsWidth(outputSlots)); - } - return widthCash; - } - - protected Figure(Diagram diagram, int id) { - this.diagram = diagram; - this.source = new Source(); - inputSlots = new ArrayList<>(5); - outputSlots = new ArrayList<>(1); - predecessors = new ArrayList<>(6); - successors = new ArrayList<>(6); - this.id = id; - idString = Integer.toString(id); - - this.position = new Point(0, 0); - this.color = Color.WHITE; - } - - public int getId() { - return id; - } - - public void setColor(Color color) { - this.color = color; - } - - public Color getColor() { - return color; - } - - public List
getPredecessors() { - return Collections.unmodifiableList(predecessors); - } - - public Set
getPredecessorSet() { - Set
result = new HashSet<>(); - for (Figure f : getPredecessors()) { - result.add(f); - } - return Collections.unmodifiableSet(result); - } - - public Set
getSuccessorSet() { - Set
result = new HashSet<>(); - for (Figure f : getSuccessors()) { - result.add(f); - } - return Collections.unmodifiableSet(result); - } - - public List
getSuccessors() { - return Collections.unmodifiableList(successors); - } - - protected void addPredecessor(Figure f) { - this.predecessors.add(f); - } - - protected void addSuccessor(Figure f) { - this.successors.add(f); - } - - protected void removePredecessor(Figure f) { - assert predecessors.contains(f); - predecessors.remove(f); - } - - protected void removeSuccessor(Figure f) { - assert successors.contains(f); - successors.remove(f); - } - - @Override - public void setPosition(Point p) { - this.position = p; - } - - @Override - public Point getPosition() { - return position; - } - - public Diagram getDiagram() { - return diagram; - } - - @Override - public Source getSource() { - return source; - } - - public InputSlot createInputSlot() { - InputSlot slot = new InputSlot(this, -1); - inputSlots.add(slot); - return slot; - } - - public InputSlot createInputSlot(int index) { - InputSlot slot = new InputSlot(this, index); - inputSlots.add(slot); - Collections.sort(inputSlots, Slot.slotIndexComparator); - return slot; - } - - public void removeSlot(Slot s) { - - assert inputSlots.contains(s) || outputSlots.contains(s); - - List connections = new ArrayList<>(s.getConnections()); - for (Connection c : connections) { - c.remove(); - } - - if (inputSlots.contains(s)) { - inputSlots.remove(s); - } else if (outputSlots.contains(s)) { - outputSlots.remove(s); - } - } - - public OutputSlot createOutputSlot() { - OutputSlot slot = new OutputSlot(this, -1); - outputSlots.add(slot); - return slot; - } - - public OutputSlot createOutputSlot(int index) { - OutputSlot slot = new OutputSlot(this, index); - outputSlots.add(slot); - Collections.sort(outputSlots, Slot.slotIndexComparator); - return slot; - } - - public List getInputSlots() { - return Collections.unmodifiableList(inputSlots); - } - - public Set getSlots() { - Set result = new HashSet<>(); - result.addAll(getInputSlots()); - result.addAll(getOutputSlots()); - return result; - } - - public List getOutputSlots() { - return Collections.unmodifiableList(outputSlots); - } - - void removeInputSlot(InputSlot s) { - s.removeAllConnections(); - inputSlots.remove(s); - } - - void removeOutputSlot(OutputSlot s) { - s.removeAllConnections(); - outputSlots.remove(s); - } - - public String[] getLines() { - if (lines == null) { - updateLines(); - } - return lines; - } - - public void updateLines() { - String[] strings = diagram.getNodeText().split("\n"); - String[] result = new String[strings.length]; - - for (int i = 0; i < strings.length; i++) { - result[i] = resolveString(strings[i], getProperties()); - } - - lines = result; - } - - public static final String resolveString(String string, Properties properties) { - - StringBuilder sb = new StringBuilder(); - boolean inBrackets = false; - StringBuilder curIdent = new StringBuilder(); - - for (int i = 0; i < string.length(); i++) { - char c = string.charAt(i); - if (inBrackets) { - if (c == ']') { - String value = properties.get(curIdent.toString()); - if (value == null) { - value = ""; - } - sb.append(value); - inBrackets = false; - } else { - curIdent.append(c); - } - } else { - if (c == '[') { - inBrackets = true; - curIdent = new StringBuilder(); - } else { - sb.append(c); - } - } - } - - return sb.toString(); - } - - @Override - public Dimension getSize() { - if (VERTICAL_LAYOUT) { - int width = Math.max(getWidth(), Figure.SLOT_WIDTH * (Math.max(inputSlots.size(), outputSlots.size()) + 1)); - int height = getHeight() + 2 * Figure.SLOT_WIDTH - 2 * Figure.OVERLAPPING; - - - return new Dimension(width, height); - } else { - int width = getWidth() + 2 * Figure.SLOT_WIDTH - 2*Figure.OVERLAPPING; - int height = Figure.SLOT_WIDTH * (Math.max(inputSlots.size(), outputSlots.size()) + 1); - return new Dimension(width, height); - } - } - - @Override - public String toString() { - return idString; - } - - @Override - public boolean isRoot() { - - List sourceNodes = source.getSourceNodes(); - if (sourceNodes.size() > 0 && sourceNodes.get(0).getProperties().get("name") != null) { - return source.getSourceNodes().get(0).getProperties().get("name").equals("Root"); - } else { - return false; - } - } - - @Override - public int compareTo(Vertex f) { - return toString().compareTo(f.toString()); - } - - public Rectangle getBounds() { - return new Rectangle(this.getPosition(), new Dimension(this.getWidth(), this.getHeight())); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/src/com/sun/hotspot/igv/graph/InputSlot.java --- a/visualizer/Graph/src/com/sun/hotspot/igv/graph/InputSlot.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.graph; - -import java.awt.Point; -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public class InputSlot extends Slot { - - protected InputSlot(Figure figure, int wantedIndex) { - super(figure, wantedIndex); - } - - @Override - public int getPosition() { - return getFigure().getInputSlots().indexOf(this); - } - - @Override - public void setPosition(int position) { - List inputSlots = getFigure().inputSlots; - InputSlot s = inputSlots.remove(position); - inputSlots.add(position, s); - } - @Override - public Point getRelativePosition() { - int gap = getFigure().getWidth() - Figure.getSlotsWidth(getFigure().getInputSlots()); - double gapRatio = (double)gap / (double)(getFigure().getInputSlots().size() + 1); - int gapAmount = (int)((getPosition() + 1)*gapRatio); - return new Point(gapAmount + Figure.getSlotsWidth(Figure.getAllBefore(getFigure().getInputSlots(), this)) + getWidth()/2, -Figure.SLOT_START); - //return new Point((getFigure().getWidth() / (getFigure().getInputSlots().size() * 2)) * (getPosition() * 2 + 1), -Figure.SLOT_START); - } - - @Override - public String toString() { - return "InputSlot[figure=" + this.getFigure().toString() + ", position=" + getPosition() + "]"; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/src/com/sun/hotspot/igv/graph/InvertSelector.java --- a/visualizer/Graph/src/com/sun/hotspot/igv/graph/InvertSelector.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.graph; - -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public class InvertSelector implements Selector { - - private Selector selector; - - public InvertSelector(Selector selector) { - this.selector = selector; - } - - @Override - public List
selected(Diagram d) { - - List
result = new ArrayList<>(); - List
otherResult = selector.selected(d); - for (Figure f : d.getFigures()) { - if (!otherResult.contains(f)) { - result.add(f); - } - } - - return result; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/src/com/sun/hotspot/igv/graph/MatcherSelector.java --- a/visualizer/Graph/src/com/sun/hotspot/igv/graph/MatcherSelector.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.graph; - -import com.sun.hotspot.igv.data.Properties; -import com.sun.hotspot.igv.data.Properties.PropertyMatcher; -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public class MatcherSelector implements Selector { - - private PropertyMatcher matcher; - - public MatcherSelector(PropertyMatcher matcher) { - this.matcher = matcher; - } - - @Override - public List
selected(Diagram d) { - Properties.PropertySelector
selector = new Properties.PropertySelector<>(d.getFigures()); - List
list = selector.selectMultiple(matcher); - return list; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/src/com/sun/hotspot/igv/graph/OrSelector.java --- a/visualizer/Graph/src/com/sun/hotspot/igv/graph/OrSelector.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.graph; - -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public class OrSelector implements Selector { - - private Selector selector1; - private Selector selector2; - - /** Creates a new instance of OrSelector */ - public OrSelector(Selector s1, Selector s2) { - this.selector1 = s1; - this.selector2 = s2; - } - - @Override - public List
selected(Diagram d) { - - List
l1 = selector1.selected(d); - List
l2 = selector2.selected(d); - - for (Figure f : l2) { - if (!l1.contains(f)) { - l1.add(f); - } - } - - return l1; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/src/com/sun/hotspot/igv/graph/OutputSlot.java --- a/visualizer/Graph/src/com/sun/hotspot/igv/graph/OutputSlot.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.graph; - -import java.awt.Point; - -/** - * - * @author Thomas Wuerthinger - */ -public class OutputSlot extends Slot { - - protected OutputSlot(Figure figure, int wantedIndex) { - super(figure, wantedIndex); - } - - @Override - public int getPosition() { - return getFigure().getOutputSlots().indexOf(this); - } - - @Override - public void setPosition(int position) { - OutputSlot s = getFigure().outputSlots.remove(position); - getFigure().outputSlots.add(position, s); - } - - @Override - public Point getRelativePosition() { - int gap = getFigure().getWidth() - Figure.getSlotsWidth(getFigure().getOutputSlots()); - if(gap < 0) { - gap = 0; - } - double gapRatio = (double)gap / (double)(getFigure().getOutputSlots().size() + 1); - int gapAmount = (int)((getPosition() + 1)*gapRatio); - return new Point(gapAmount + Figure.getSlotsWidth(Figure.getAllBefore(getFigure().getOutputSlots(), this)) + getWidth()/2, Figure.SLOT_START); - } - - @Override - public String toString() { - return "OutputSlot[figure=" + this.getFigure().toString() + ", position=" + getPosition() + "]"; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/src/com/sun/hotspot/igv/graph/PredecessorSelector.java --- a/visualizer/Graph/src/com/sun/hotspot/igv/graph/PredecessorSelector.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.graph; - -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public class PredecessorSelector implements Selector { - - private Selector innerSelector; - - public PredecessorSelector(Selector innerSelector) { - this.innerSelector = innerSelector; - } - - @Override - public List
selected(Diagram d) { - List
inner = innerSelector.selected(d); - List
result = new ArrayList<>(); - for (Figure f : d.getFigures()) { - boolean saved = false; - for (Figure f2 : f.getSuccessors()) { - if (inner.contains(f2)) { - saved = true; - } - } - - if (saved) { - result.add(f); - } - } - - return result; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/src/com/sun/hotspot/igv/graph/Selector.java --- a/visualizer/Graph/src/com/sun/hotspot/igv/graph/Selector.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.graph; - -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public interface Selector { - - List
selected(Diagram d); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/src/com/sun/hotspot/igv/graph/Slot.java --- a/visualizer/Graph/src/com/sun/hotspot/igv/graph/Slot.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.graph; - -import com.sun.hotspot.igv.data.InputNode; -import com.sun.hotspot.igv.data.Properties; -import com.sun.hotspot.igv.data.Source; -import com.sun.hotspot.igv.layout.Port; -import com.sun.hotspot.igv.layout.Vertex; -import java.awt.Color; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics; -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public abstract class Slot implements Port, Source.Provider, Properties.Provider { - - private int wantedIndex; - private Source source; - protected List connections; - private InputNode associatedNode; - private Color color; - private String text; - private String shortName; - private Figure figure; - - protected Slot(Figure figure, int wantedIndex) { - this.figure = figure; - connections = new ArrayList<>(2); - source = new Source(); - this.wantedIndex = wantedIndex; - text = ""; - shortName = ""; - assert figure != null; - } - - @Override - public Properties getProperties() { - Properties p = new Properties(); - if (source.getSourceNodes().size() > 0) { - for (InputNode n : source.getSourceNodes()) { - p.add(n.getProperties()); - } - } else { - p.setProperty("name", "Slot"); - p.setProperty("figure", figure.getProperties().get("name")); - p.setProperty("connectionCount", Integer.toString(connections.size())); - } - return p; - } - public static final Comparator slotIndexComparator = new Comparator() { - - @Override - public int compare(Slot o1, Slot o2) { - return o1.wantedIndex - o2.wantedIndex; - } - }; - public static final Comparator slotFigureComparator = new Comparator() { - - @Override - public int compare(Slot o1, Slot o2) { - return o1.figure.getId() - o2.figure.getId(); - } - }; - - public InputNode getAssociatedNode() { - return associatedNode; - } - - public void setAssociatedNode(InputNode node) { - associatedNode = node; - } - - public int getWidth() { - if (shortName == null || shortName.length() <= 1) { - return Figure.SLOT_WIDTH; - } else { - BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); - Graphics g = image.getGraphics(); - g.setFont(figure.getDiagram().getSlotFont().deriveFont(Font.BOLD)); - FontMetrics metrics = g.getFontMetrics(); - return Math.max(Figure.SLOT_WIDTH, metrics.stringWidth(shortName) + 6); - } - } - - public int getWantedIndex() { - return wantedIndex; - } - - @Override - public Source getSource() { - return source; - } - - public String getText() { - return text; - } - - public void setShortName(String s) { - assert s != null; -// assert s.length() <= 2; - this.shortName = s; - - } - - public String getShortName() { - return shortName; - } - - public String getToolTipText() { - StringBuilder sb = new StringBuilder(); - sb.append(text); - - for (InputNode n : getSource().getSourceNodes()) { - sb.append("Node (ID=" + n.getId() + "): " + n.getProperties().get("name")); - sb.append("
"); - } - - return sb.toString(); - } - - public boolean shouldShowName() { - return getShortName() != null && getShortName().length() > 0; - } - - public void setText(String s) { - if (s == null) { - s = ""; - } - this.text = s; - } - - public Figure getFigure() { - assert figure != null; - return figure; - } - - public Color getColor() { - return this.color; - } - - public void setColor(Color c) { - color = c; - } - - public List getConnections() { - return Collections.unmodifiableList(connections); - } - - public void removeAllConnections() { - List connectionsCopy = new ArrayList<>(this.connections); - for (Connection c : connectionsCopy) { - c.remove(); - } - } - - @Override - public Vertex getVertex() { - return figure; - } - - public abstract int getPosition(); - - public abstract void setPosition(int position); -} - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/src/com/sun/hotspot/igv/graph/SuccessorSelector.java --- a/visualizer/Graph/src/com/sun/hotspot/igv/graph/SuccessorSelector.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.graph; - -import java.util.ArrayList; -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public class SuccessorSelector implements Selector { - - private Selector innerSelector; - - public SuccessorSelector(Selector innerSelector) { - this.innerSelector = innerSelector; - } - - @Override - public List
selected(Diagram d) { - List
inner = innerSelector.selected(d); - List
result = new ArrayList<>(); - for (Figure f : d.getFigures()) { - boolean saved = false; - for (Figure f2 : f.getPredecessors()) { - if (inner.contains(f2)) { - saved = true; - } - } - - if (saved) { - result.add(f); - } - } - - return result; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Graph/src/com/sun/hotspot/igv/graph/services/DiagramProvider.java --- a/visualizer/Graph/src/com/sun/hotspot/igv/graph/services/DiagramProvider.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.sun.hotspot.igv.graph.services; - -import com.sun.hotspot.igv.data.ChangedEvent; -import com.sun.hotspot.igv.graph.Diagram; - -/** - * - * @author Thomas Wuerthinger - */ -public interface DiagramProvider { - Diagram getDiagram(); - ChangedEvent getChangedEvent(); - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/HierarchicalLayout/build.xml --- a/visualizer/HierarchicalLayout/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project com.sun.hotspot.igv.hierarchicallayout. - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/HierarchicalLayout/manifest.mf --- a/visualizer/HierarchicalLayout/manifest.mf Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.sun.hotspot.igv.hierarchicallayout -OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/hierarchicallayout/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/HierarchicalLayout/nbproject/build-impl.xml --- a/visualizer/HierarchicalLayout/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/HierarchicalLayout/nbproject/genfiles.properties --- a/visualizer/HierarchicalLayout/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -build.xml.data.CRC32=de087df9 -build.xml.script.CRC32=98977c36 -build.xml.stylesheet.CRC32=79c3b980 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=de087df9 -nbproject/build-impl.xml.script.CRC32=0d734625 -nbproject/build-impl.xml.stylesheet.CRC32=deb65f65 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/HierarchicalLayout/nbproject/platform.properties --- a/visualizer/HierarchicalLayout/nbproject/platform.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -# Deprecated since 5.0u1; for compatibility with 5.0: -disabled.clusters=\ - apisupport1,\ - harness,\ - ide8,\ - java1,\ - nb6.0,\ - profiler2 -disabled.modules=\ - org.netbeans.core.execution,\ - org.netbeans.core.multiview,\ - org.netbeans.core.output2,\ - org.netbeans.modules.applemenu,\ - org.netbeans.modules.autoupdate.services,\ - org.netbeans.modules.autoupdate.ui,\ - org.netbeans.modules.core.kit,\ - org.netbeans.modules.favorites,\ - org.netbeans.modules.javahelp,\ - org.netbeans.modules.masterfs,\ - org.netbeans.modules.options.keymap,\ - org.netbeans.modules.sendopts,\ - org.netbeans.modules.templates,\ - org.openide.compat,\ - org.openide.execution,\ - org.openide.util.enumerations -enabled.clusters=\ - platform7 -nbjdk.active=JDK_1.6 -nbplatform.active=default diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/HierarchicalLayout/nbproject/project.properties --- a/visualizer/HierarchicalLayout/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -javac.source=1.7 -javac.compilerargs=-Xlint -Xlint:-serial diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/HierarchicalLayout/nbproject/project.xml --- a/visualizer/HierarchicalLayout/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - com.sun.hotspot.igv.hierarchicallayout - - - - com.sun.hotspot.igv.layout - - - - 1.0 - - - - - com.sun.hotspot.igv.hierarchicallayout - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/HierarchicalLayout/nbproject/suite.properties --- a/visualizer/HierarchicalLayout/nbproject/suite.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -suite.dir=${basedir}/.. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Bundle.properties --- a/visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -OpenIDE-Module-Name=HierarchicalLayout diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Edge.java --- a/visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Edge.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.hierarchicallayout; - -/** - * - * @author Thomas Wuerthinger - */ -public class Edge { - - private E data; - private Node source; - private Node dest; - - protected Edge(Graph graph, Node source, Node dest, E data) { - setData(data); - this.source = source; - this.dest = dest; - assert source != null; - assert dest != null; - assert source.getGraph() == dest.getGraph(); - assert source.getGraph() != null; - assert dest.getGraph() != null; - } - - public Node getSource() { - return source; - } - - public Node getDest() { - return dest; - } - - public E getData() { - return data; - } - - public void setData(E e) { - data = e; - } - - public void remove() { - source.getGraph().removeEdge(this, null); - } - - public boolean isSelfLoop() { - return source == dest; - } - - public void reverse() { - - // Remove from current source / dest - source.removeOutEdge(this); - dest.removeInEdge(this); - - Node tmp = source; - source = dest; - dest = tmp; - - // Add to new source / dest - source.addOutEdge(this); - dest.addInEdge(this); - } - - @Override - public String toString() { - return "Edge (" + source + " -- " + dest + "): " + data; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Graph.java --- a/visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Graph.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,292 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.hierarchicallayout; - -import java.util.*; - -/** - * - * @author Thomas Wuerthinger - */ -public class Graph { - - private HashMap> nodes; - private HashMap> edges; - private List> nodeList; - - public Graph() { - nodes = new HashMap<>(); - edges = new HashMap<>(); - nodeList = new ArrayList<>(); - } - - public Node createNode(N data, Object key) { - Node n = new Node<>(this, data); - assert key == null || !nodes.containsKey(key); - if (key != null) { - nodes.put(key, n); - } - nodeList.add(n); - return n; - } - - public Edge createEdge(Node source, Node dest, E data, Object key) { - Edge e = new Edge<>(this, source, dest, data); - source.addOutEdge(e); - dest.addInEdge(e); - if (key != null) { - edges.put(key, e); - } - return e; - } - - public Node getNode(Object key) { - return nodes.get(key); - } - - public Edge getEdge(Object key) { - return edges.get(key); - } - - public Collection> getEdges() { - return Collections.unmodifiableCollection(edges.values()); - } - - public Collection> getNodes() { - return Collections.unmodifiableList(nodeList); - } - - public void removeEdge(Edge e, Object key) { - assert key == null || edges.containsKey(key); - if (key != null) { - edges.remove(key); - } - e.getSource().removeOutEdge(e); - e.getDest().removeInEdge(e); - } - - public class DFSTraversalVisitor { - - public void visitNode(Node n) { - } - - public boolean visitEdge(Edge e, boolean backEdge) { - return true; - } - } - - public class BFSTraversalVisitor { - - public void visitNode(Node n, int depth) { - } - } - - public List> getNodesWithInDegree(int x) { - return getNodesWithInDegree(x, true); - } - - public List> getNodesWithInDegree(int x, boolean countSelfLoops) { - - List> result = new ArrayList<>(); - for (Node n : getNodes()) { - if (n.getInDegree(countSelfLoops) == x) { - result.add(n); - } - } - - return result; - - } - - private void markReachable(Node startingNode) { - ArrayList> arr = new ArrayList<>(); - arr.add(startingNode); - for (Node n : getNodes()) { - n.setReachable(false); - } - traverseDFS(arr, new DFSTraversalVisitor() { - - @Override - public void visitNode(Node n) { - n.setReachable(true); - } - }); - } - - public void traverseBFS(Node startingNode, BFSTraversalVisitor tv, boolean longestPath) { - - if (longestPath) { - markReachable(startingNode); - } - - for (Node n : getNodes()) { - n.setVisited(false); - n.setActive(false); - } - - Queue> queue = new LinkedList<>(); - queue.add(startingNode); - startingNode.setVisited(true); - int layer = 0; - Node lastOfLayer = startingNode; - Node lastAdded = null; - - while (!queue.isEmpty()) { - - Node current = queue.poll(); - tv.visitNode(current, layer); - current.setActive(false); - - - for (Edge e : current.getOutEdges()) { - if (!e.getDest().isVisited()) { - - boolean allow = true; - if (longestPath) { - for (Node pred : e.getDest().getPredecessors()) { - if ((!pred.isVisited() || pred.isActive()) && pred.isReachable()) { - allow = false; - break; - } - } - } - - if (allow) { - queue.offer(e.getDest()); - lastAdded = e.getDest(); - e.getDest().setVisited(true); - e.getDest().setActive(true); - } - } - } - - if (current == lastOfLayer && !queue.isEmpty()) { - lastOfLayer = lastAdded; - layer++; - } - } - } - - public void traverseDFS(DFSTraversalVisitor tv) { - traverseDFS(getNodes(), tv); - } - - public void traverseDFS(Collection> startingNodes, DFSTraversalVisitor tv) { - - for (Node n : getNodes()) { - n.setVisited(false); - n.setActive(false); - } - - boolean result = false; - for (Node n : startingNodes) { - traverse(tv, n); - } - } - - private void traverse(DFSTraversalVisitor tv, Node n) { - - if (!n.isVisited()) { - n.setVisited(true); - n.setActive(true); - tv.visitNode(n); - - for (Edge e : n.getOutEdges()) { - - Node next = e.getDest(); - if (next.isActive()) { - tv.visitEdge(e, true); - } else { - if (tv.visitEdge(e, false)) { - traverse(tv, next); - } - } - } - - n.setActive(false); - } - - } - - public boolean hasCycles() { - - for (Node n : getNodes()) { - n.setVisited(false); - n.setActive(false); - } - - boolean result = false; - for (Node n : getNodes()) { - result |= checkCycles(n); - if (result) { - break; - } - } - return result; - } - - private boolean checkCycles(Node n) { - - if (n.isActive()) { - return true; - } - - if (!n.isVisited()) { - - n.setVisited(true); - n.setActive(true); - - for (Node succ : n.getSuccessors()) { - if (checkCycles(succ)) { - return true; - } - } - - n.setActive(false); - - } - - return false; - } - - @Override - public String toString() { - - StringBuilder s = new StringBuilder(); - s.append("Nodes: "); - for (Node n : getNodes()) { - s.append(n.toString()); - s.append("\n"); - } - - s.append("Edges: "); - - for (Edge e : getEdges()) { - s.append(e.toString()); - s.append("\n"); - } - - return s.toString(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalLayoutManager.java --- a/visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/HierarchicalLayoutManager.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1749 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.hierarchicallayout; - -import com.sun.hotspot.igv.layout.LayoutGraph; -import com.sun.hotspot.igv.layout.LayoutManager; -import com.sun.hotspot.igv.layout.Link; -import com.sun.hotspot.igv.layout.Vertex; -import java.awt.Dimension; -import java.awt.Point; -import java.util.*; - -/** - * - * @author Thomas Wuerthinger - */ -public class HierarchicalLayoutManager implements LayoutManager { - - public static final boolean TRACE = false; - public static final boolean CHECK = false; - public static final int SWEEP_ITERATIONS = 1; - public static final int CROSSING_ITERATIONS = 2; - public static final int DUMMY_HEIGHT = 1; - public static final int DUMMY_WIDTH = 1; - public static final int X_OFFSET = 9; - public static final int LAYER_OFFSET = 30; - public static final int MAX_LAYER_LENGTH = -1; - public static final int MIN_LAYER_DIFFERENCE = 1; - public static final int VIP_BONUS = 10; - - public enum Combine { - - NONE, - SAME_INPUTS, - SAME_OUTPUTS - } - // Options - private Combine combine; - private int dummyWidth; - private int dummyHeight; - private int xOffset; - private int layerOffset; - private int maxLayerLength; - private int minLayerDifference; - // Algorithm global datastructures - private Set reversedLinks; - private List nodes; - private HashMap vertexToLayoutNode; - private HashMap> reversedLinkStartPoints; - private HashMap> reversedLinkEndPoints; - private HashMap bottomEdgeHash; - private HashMap> splitStartPoints; - private HashMap> splitEndPoints; - private LayoutGraph graph; - private List[] layers; - private int layerCount; - private Set firstLayerHint; - private Set lastLayerHint; - private Set importantLinks; - private Set linksToFollow; - - private class LayoutNode { - - public int x; - public int y; - public int width; - public int height; - public int layer = -1; - public int xOffset; - public int yOffset; - public int bottomYOffset; - public Vertex vertex; // Only used for non-dummy nodes, otherwise null - - public List preds = new ArrayList<>(); - public List succs = new ArrayList<>(); - public HashMap outOffsets = new HashMap<>(); - public HashMap inOffsets = new HashMap<>(); - public int pos = -1; // Position within layer - - public int crossingNumber; - - @Override - public String toString() { - return "Node " + vertex; - } - } - - private class LayoutEdge { - - public LayoutNode from; - public LayoutNode to; - public int relativeFrom; - public int relativeTo; - public Link link; - public boolean vip; - } - - private abstract class AlgorithmPart { - - public void start() { - if (CHECK) { - preCheck(); - } - - long start = 0; - if (TRACE) { - System.out.println("##################################################"); - System.out.println("Starting part " + this.getClass().getName()); - start = System.currentTimeMillis(); - } - run(); - if (TRACE) { - System.out.println("Timing for " + this.getClass().getName() + " is " + (System.currentTimeMillis() - start)); - printStatistics(); - } - - if (CHECK) { - postCheck(); - } - } - - protected abstract void run(); - - protected void printStatistics() { - } - - protected void postCheck() { - } - - protected void preCheck() { - } - } - - public HierarchicalLayoutManager() { - this(Combine.NONE); - } - - public HierarchicalLayoutManager(Combine b) { - this.combine = b; - this.dummyWidth = DUMMY_WIDTH; - this.dummyHeight = DUMMY_HEIGHT; - this.xOffset = X_OFFSET; - this.layerOffset = LAYER_OFFSET; - this.maxLayerLength = MAX_LAYER_LENGTH; - this.minLayerDifference = MIN_LAYER_DIFFERENCE; - this.linksToFollow = new HashSet<>(); - } - - public int getMaxLayerLength() { - return maxLayerLength; - } - - public void setMaxLayerLength(int v) { - maxLayerLength = v; - } - - public void setMinLayerDifference(int v) { - minLayerDifference = v; - } - - @Override - public void doLayout(LayoutGraph graph) { - doLayout(graph, new HashSet(), new HashSet(), new HashSet()); - - } - - @Override - public void doLayout(LayoutGraph graph, Set firstLayerHint, Set lastLayerHint, Set importantLinks) { - - this.importantLinks = importantLinks; - this.graph = graph; - this.firstLayerHint = firstLayerHint; - this.lastLayerHint = lastLayerHint; - - vertexToLayoutNode = new HashMap<>(); - reversedLinks = new HashSet<>(); - reversedLinkStartPoints = new HashMap<>(); - reversedLinkEndPoints = new HashMap<>(); - bottomEdgeHash = new HashMap<>(); - nodes = new ArrayList<>(); - splitStartPoints = new HashMap<>(); - splitEndPoints = new HashMap<>(); - - // ############################################################# - // Step 1: Build up data structure - new BuildDatastructure().start(); - - // ############################################################# - // STEP 2: Reverse edges, handle backedges - new ReverseEdges().start(); - - for (LayoutNode n : nodes) { - ArrayList tmpArr = new ArrayList<>(); - for (LayoutEdge e : n.succs) { - if (importantLinks.contains(e.link)) { - tmpArr.add(e); - } - } - - for (LayoutEdge e : tmpArr) { - //System.out.println("Removed " + e); - e.from.succs.remove(e); - e.to.preds.remove(e); - } - } - - // ############################################################# - // STEP 3: Assign layers - new AssignLayers().start(); - - // ############################################################# - // STEP 4: Create dummy nodes - new CreateDummyNodes().start(); - - // ############################################################# - // STEP 5: Crossing Reduction - new CrossingReduction().start(); - - // ############################################################# - // STEP 7: Assign X coordinates - new AssignXCoordinates().start(); - - // ############################################################# - // STEP 6: Assign Y coordinates - new AssignYCoordinates().start(); - - // ############################################################# - // STEP 8: Write back to interface - new WriteResult().start(); - } - - private class WriteResult extends AlgorithmPart { - - private int pointCount; - - @Override - protected void run() { - - HashMap vertexPositions = new HashMap<>(); - HashMap> linkPositions = new HashMap<>(); - for (Vertex v : graph.getVertices()) { - LayoutNode n = vertexToLayoutNode.get(v); - assert !vertexPositions.containsKey(v); - vertexPositions.put(v, new Point(n.x + n.xOffset, n.y + n.yOffset)); - } - - for (LayoutNode n : nodes) { - - for (LayoutEdge e : n.preds) { - if (e.link != null) { - ArrayList points = new ArrayList<>(); - - Point p = new Point(e.to.x + e.relativeTo, e.to.y + e.to.yOffset + e.link.getTo().getRelativePosition().y); - points.add(p); - if (e.to.inOffsets.containsKey(e.relativeTo)) { - points.add(new Point(p.x, p.y + e.to.inOffsets.get(e.relativeTo) + e.link.getTo().getRelativePosition().y)); - } - - LayoutNode cur = e.from; - LayoutNode other = e.to; - LayoutEdge curEdge = e; - while (cur.vertex == null && cur.preds.size() != 0) { - if (points.size() > 1 && points.get(points.size() - 1).x == cur.x + cur.width / 2 && points.get(points.size() - 2).x == cur.x + cur.width / 2) { - points.remove(points.size() - 1); - } - points.add(new Point(cur.x + cur.width / 2, cur.y + cur.height)); - if (points.size() > 1 && points.get(points.size() - 1).x == cur.x + cur.width / 2 && points.get(points.size() - 2).x == cur.x + cur.width / 2) { - points.remove(points.size() - 1); - } - points.add(new Point(cur.x + cur.width / 2, cur.y)); - assert cur.preds.size() == 1; - curEdge = cur.preds.get(0); - cur = curEdge.from; - } - - p = new Point(cur.x + curEdge.relativeFrom, cur.y + cur.height - cur.bottomYOffset + (curEdge.link == null ? 0 : curEdge.link.getFrom().getRelativePosition().y)); - if (curEdge.from.outOffsets.containsKey(curEdge.relativeFrom)) { - points.add(new Point(p.x, p.y + curEdge.from.outOffsets.get(curEdge.relativeFrom) + (curEdge.link == null ? 0 : curEdge.link.getFrom().getRelativePosition().y))); - } - points.add(p); - - Collections.reverse(points); - - - - if (cur.vertex == null && cur.preds.size() == 0) { - - if (reversedLinkEndPoints.containsKey(e.link)) { - for (Point p1 : reversedLinkEndPoints.get(e.link)) { - points.add(new Point(p1.x + e.to.x, p1.y + e.to.y)); - } - } - - if (splitStartPoints.containsKey(e.link)) { - points.add(0, null); - points.addAll(0, splitStartPoints.get(e.link)); - - //checkPoints(points); - if (reversedLinks.contains(e.link)) { - Collections.reverse(points); - } - assert !linkPositions.containsKey(e.link); - linkPositions.put(e.link, points); - } else { - splitEndPoints.put(e.link, points); - } - - } else { - if (reversedLinks.contains(e.link)) { - Collections.reverse(points); - } - if (reversedLinkStartPoints.containsKey(e.link)) { - for (Point p1 : reversedLinkStartPoints.get(e.link)) { - points.add(new Point(p1.x + cur.x, p1.y + cur.y)); - } - } - - if (reversedLinkEndPoints.containsKey(e.link)) { - for (Point p1 : reversedLinkEndPoints.get(e.link)) { - points.add(0, new Point(p1.x + other.x, p1.y + other.y)); - } - } - - assert !linkPositions.containsKey(e.link); - linkPositions.put(e.link, points); - } - pointCount += points.size(); - - // No longer needed! - e.link = null; - } - } - - for (LayoutEdge e : n.succs) { - if (e.link != null) { - ArrayList points = new ArrayList<>(); - Point p = new Point(e.from.x + e.relativeFrom, e.from.y + e.from.height - e.from.bottomYOffset + e.link.getFrom().getRelativePosition().y); - points.add(p); - if (e.from.outOffsets.containsKey(e.relativeFrom)) { - points.add(new Point(p.x, p.y + e.from.outOffsets.get(e.relativeFrom) + e.link.getFrom().getRelativePosition().y)); - } - - LayoutNode cur = e.to; - LayoutNode other = e.from; - LayoutEdge curEdge = e; - while (cur.vertex == null && cur.succs.size() != 0) { - if (points.size() > 1 && points.get(points.size() - 1).x == cur.x + cur.width / 2 && points.get(points.size() - 2).x == cur.x + cur.width / 2) { - points.remove(points.size() - 1); - } - points.add(new Point(cur.x + cur.width / 2, cur.y)); - if (points.size() > 1 && points.get(points.size() - 1).x == cur.x + cur.width / 2 && points.get(points.size() - 2).x == cur.x + cur.width / 2) { - points.remove(points.size() - 1); - } - points.add(new Point(cur.x + cur.width / 2, cur.y + cur.height)); - if (cur.succs.size() == 0) { - break; - } - assert cur.succs.size() == 1; - curEdge = cur.succs.get(0); - cur = curEdge.to; - } - - - p = new Point(cur.x + curEdge.relativeTo, cur.y + cur.yOffset + ((curEdge.link == null) ? 0 : curEdge.link.getTo().getRelativePosition().y)); - points.add(p); - if (curEdge.to.inOffsets.containsKey(curEdge.relativeTo)) { - points.add(new Point(p.x, p.y + curEdge.to.inOffsets.get(curEdge.relativeTo) + ((curEdge.link == null) ? 0 : curEdge.link.getTo().getRelativePosition().y))); - } - - - if (cur.succs.size() == 0 && cur.vertex == null) { - if (reversedLinkStartPoints.containsKey(e.link)) { - for (Point p1 : reversedLinkStartPoints.get(e.link)) { - points.add(0, new Point(p1.x + other.x, p1.y + other.y)); - } - } - - if (splitEndPoints.containsKey(e.link)) { - points.add(null); - points.addAll(splitEndPoints.get(e.link)); - - //checkPoints(points); - if (reversedLinks.contains(e.link)) { - Collections.reverse(points); - } - assert !linkPositions.containsKey(e.link); - linkPositions.put(e.link, points); - } else { - splitStartPoints.put(e.link, points); - } - } else { - - if (reversedLinkStartPoints.containsKey(e.link)) { - for (Point p1 : reversedLinkStartPoints.get(e.link)) { - points.add(0, new Point(p1.x + other.x, p1.y + other.y)); - } - } - if (reversedLinkEndPoints.containsKey(e.link)) { - for (Point p1 : reversedLinkEndPoints.get(e.link)) { - points.add(new Point(p1.x + cur.x, p1.y + cur.y)); - } - } - if (reversedLinks.contains(e.link)) { - Collections.reverse(points); - } - //checkPoints(points); - assert !linkPositions.containsKey(e.link); - linkPositions.put(e.link, points); - } - - pointCount += points.size(); - e.link = null; - } - } - } - - int minX = Integer.MAX_VALUE; - int minY = Integer.MAX_VALUE; - for (Vertex v : vertexPositions.keySet()) { - Point p = vertexPositions.get(v); - minX = Math.min(minX, p.x); - minY = Math.min(minY, p.y); - } - - for (Link l : linkPositions.keySet()) { - List points = linkPositions.get(l); - for (Point p : points) { - if (p != null) { - minX = Math.min(minX, p.x); - minY = Math.min(minY, p.y); - } - } - - } - - for (Vertex v : vertexPositions.keySet()) { - Point p = vertexPositions.get(v); - p.x -= minX; - p.y -= minY; - v.setPosition(p); - } - - for (Link l : linkPositions.keySet()) { - List points = linkPositions.get(l); - for (Point p : points) { - if (p != null) { - p.x -= minX; - p.y -= minY; - } - } - l.setControlPoints(points); - - } - } - - @Override - protected void printStatistics() { - System.out.println("Number of nodes: " + nodes.size()); - int edgeCount = 0; - for (LayoutNode n : nodes) { - edgeCount += n.succs.size(); - } - System.out.println("Number of edges: " + edgeCount); - System.out.println("Number of points: " + pointCount); - } - } - - private static class Segment { - - public float d; - public int orderNumber = -1; - public ArrayList nodes = new ArrayList<>(); - public HashSet succs = new HashSet<>(); - public HashSet preds = new HashSet<>(); - public Region region; - } - private static final Comparator segmentComparator = new Comparator() { - - @Override - public int compare(Segment s1, Segment s2) { - return s1.orderNumber - s2.orderNumber; - } - }; - - private static class Region { - - public float d; - public int minOrderNumber; - public SortedSet segments = new TreeSet<>(segmentComparator); - public HashSet succs = new HashSet<>(4); - public HashSet preds = new HashSet<>(4); - } - private static final Comparator regionComparator = new Comparator() { - - @Override - public int compare(Region r1, Region r2) { - return r1.minOrderNumber - r2.minOrderNumber; - } - }; - private static final Comparator nodePositionComparator = new Comparator() { - - @Override - public int compare(LayoutNode n1, LayoutNode n2) { - return n1.pos - n2.pos; - } - }; - private static final Comparator nodeProcessingDownComparator = new Comparator() { - @Override - public int compare(LayoutNode n1, LayoutNode n2) { - if (n1.vertex == null) { - if (n2.vertex == null) { - return 0; - } - return -1; - } - if (n2.vertex == null) { - return 1; - } - return n1.preds.size() - n2.preds.size(); - } - }; - private static final Comparator nodeProcessingUpComparator = new Comparator() { - - @Override - public int compare(LayoutNode n1, LayoutNode n2) { - if (n1.vertex == null) { - if (n2.vertex == null) { - return 0; - } - return -1; - } - if (n2.vertex == null) { - return 1; - } - return n1.succs.size() - n2.succs.size(); - } - }; - - private class AssignXCoordinates extends AlgorithmPart { - - private ArrayList[] space; - private ArrayList[] downProcessingOrder; - private ArrayList[] upProcessingOrder; - - private void initialPositions() { - for (LayoutNode n : nodes) { - n.x = space[n.layer].get(n.pos); - } - } - - @SuppressWarnings("unchecked") - private void createArrays() { - space = new ArrayList[layers.length]; - downProcessingOrder = new ArrayList[layers.length]; - upProcessingOrder = new ArrayList[layers.length]; - } - - @Override - protected void run() { - createArrays(); - - for (int i = 0; i < layers.length; i++) { - space[i] = new ArrayList<>(); - downProcessingOrder[i] = new ArrayList<>(); - upProcessingOrder[i] = new ArrayList<>(); - - int curX = 0; - for (LayoutNode n : layers[i]) { - space[i].add(curX); - curX += n.width + xOffset; - downProcessingOrder[i].add(n); - upProcessingOrder[i].add(n); - } - - Collections.sort(downProcessingOrder[i], nodeProcessingDownComparator); - Collections.sort(upProcessingOrder[i], nodeProcessingUpComparator); - } - - initialPositions(); - for (int i = 0; i < SWEEP_ITERATIONS; i++) { - sweepDown(); - sweepUp(); - } - - sweepDown(); - //for (int i = 0; i < SWEEP_ITERATIONS; i++) { - // doubleSweep(); - //} - } - - private int calculateOptimalDown(LayoutNode n) { - int size = n.preds.size(); - if (size == 0) { - return n.x; - } - int[] values = new int[size]; - for (int i = 0; i < size; i++) { - LayoutEdge e = n.preds.get(i); - values[i] = e.from.x + e.relativeFrom - e.relativeTo; - if (e.vip) { - return values[i]; - } - } - return median(values); - } - - private int calculateOptimalBoth(LayoutNode n) { - if (n.preds.size() == n.succs.size()) { - return n.x; - } - - int[] values = new int[n.preds.size() + n.succs.size()]; - int i = 0; - - for (LayoutEdge e : n.preds) { - values[i] = e.from.x + e.relativeFrom - e.relativeTo; - i++; - } - - for (LayoutEdge e : n.succs) { - values[i] = e.to.x + e.relativeTo - e.relativeFrom; - i++; - } - - return median(values); - } - - private int calculateOptimalUp(LayoutNode n) { - int size = n.succs.size(); - if (size == 0) { - return n.x; - } - int[] values = new int[size]; - for (int i = 0; i < size; i++) { - LayoutEdge e = n.succs.get(i); - values[i] = e.to.x + e.relativeTo - e.relativeFrom; - if (e.vip) { - return values[i]; - } - } - return median(values); - } - - private int median(int[] values) { - Arrays.sort(values); - if (values.length % 2 == 0) { - return (values[values.length / 2 - 1] + values[values.length / 2]) / 2; - } else { - return values[values.length / 2]; - } - } - - private void sweepUp() { - for (int i = layers.length - 1; i >= 0; i--) { - NodeRow r = new NodeRow(space[i]); - for (LayoutNode n : upProcessingOrder[i]) { - int optimal = calculateOptimalUp(n); - r.insert(n, optimal); - } - } - } - - private void doubleSweep() { - for (int i = layers.length - 2; i >= 0; i--) { - NodeRow r = new NodeRow(space[i]); - for (LayoutNode n : upProcessingOrder[i]) { - int optimal = calculateOptimalBoth(n); - r.insert(n, optimal); - } - } - } - - private void sweepDown() { - for (int i = 1; i < layers.length; i++) { - NodeRow r = new NodeRow(space[i]); - for (LayoutNode n : downProcessingOrder[i]) { - int optimal = calculateOptimalDown(n); - r.insert(n, optimal); - } - } - } - } - - private static class NodeRow { - - private TreeSet treeSet; - private ArrayList space; - - public NodeRow(ArrayList space) { - treeSet = new TreeSet<>(nodePositionComparator); - this.space = space; - } - - public int offset(LayoutNode n1, LayoutNode n2) { - int v1 = space.get(n1.pos) + n1.width; - int v2 = space.get(n2.pos); - return v2 - v1; - } - - public void insert(LayoutNode n, int pos) { - - SortedSet headSet = treeSet.headSet(n); - - LayoutNode leftNeighbor = null; - int minX = Integer.MIN_VALUE; - if (!headSet.isEmpty()) { - leftNeighbor = headSet.last(); - minX = leftNeighbor.x + leftNeighbor.width + offset(leftNeighbor, n); - } - - if (pos < minX) { - n.x = minX; - } else { - - LayoutNode rightNeighbor = null; - SortedSet tailSet = treeSet.tailSet(n); - int maxX = Integer.MAX_VALUE; - if (!tailSet.isEmpty()) { - rightNeighbor = tailSet.first(); - maxX = rightNeighbor.x - offset(n, rightNeighbor) - n.width; - } - - if (pos > maxX) { - n.x = maxX; - } else { - n.x = pos; - } - - assert minX <= maxX; - } - - treeSet.add(n); - } - } - private static Comparator crossingNodeComparator = new Comparator() { - - @Override - public int compare(LayoutNode n1, LayoutNode n2) { - return n1.crossingNumber - n2.crossingNumber; - } - }; - - private class CrossingReduction extends AlgorithmPart { - - @Override - public void preCheck() { - for (LayoutNode n : nodes) { - assert n.layer < layerCount; - } - } - - @SuppressWarnings("unchecked") - private void createLayers() { - layers = new List[layerCount]; - - for (int i = 0; i < layerCount; i++) { - layers[i] = new ArrayList<>(); - } - } - - @Override - protected void run() { - createLayers(); - - // Generate initial ordering - HashSet visited = new HashSet<>(); - for (LayoutNode n : nodes) { - if (n.layer == 0) { - layers[0].add(n); - visited.add(n); - } else if (n.preds.size() == 0) { - layers[n.layer].add(n); - visited.add(n); - } - } - - for (int i = 0; i < layers.length - 1; i++) { - for (LayoutNode n : layers[i]) { - for (LayoutEdge e : n.succs) { - if (!visited.contains(e.to)) { - visited.add(e.to); - layers[i + 1].add(e.to); - } - } - } - } - - - updatePositions(); - - initX(); - - // Optimize - for (int i = 0; i < CROSSING_ITERATIONS; i++) { - downSweep(); - upSweep(); - } - if (reversedLinks.isEmpty()) { - // This graph seems to be a tree or forest. - // A final down-sweep will usually give us a better layout. - downSweep(); - } - } - - private void initX() { - - for (int i = 0; i < layers.length; i++) { - updateXOfLayer(i); - } - } - - private void updateXOfLayer(int index) { - int x = 0; - - for (LayoutNode n : layers[index]) { - n.x = x; - x += n.width + X_OFFSET; - } - } - - private void updatePositions() { - - for (int i = 0; i < layers.length; i++) { - int z = 0; - for (LayoutNode n : layers[i]) { - n.pos = z; - z++; - } - } - } - - private void downSweep() { - - // Downsweep - for (int i = 1; i < layerCount; i++) { - - for (LayoutNode n : layers[i]) { - n.crossingNumber = 0; - } - - for (LayoutNode n : layers[i]) { - - int sum = 0; - int count = 0; - for (LayoutEdge e : n.preds) { - int cur = e.from.x + e.relativeFrom; - int factor = 1; - if (e.vip) { - factor = VIP_BONUS; - } - sum += cur*factor; - count+=factor; - } - - if (count > 0) { - sum /= count; - n.crossingNumber = sum; - } - } - - - updateCrossingNumbers(i, true); - Collections.sort(layers[i], crossingNodeComparator); - updateXOfLayer(i); - - int z = 0; - for (LayoutNode n : layers[i]) { - n.pos = z; - z++; - } - } - } - - private void updateCrossingNumbers(int index, boolean down) { - for (int i = 0; i < layers[index].size(); i++) { - LayoutNode n = layers[index].get(i); - LayoutNode prev = null; - if (i > 0) { - prev = layers[index].get(i - 1); - } - LayoutNode next = null; - if (i < layers[index].size() - 1) { - next = layers[index].get(i + 1); - } - - boolean cond = n.succs.isEmpty(); - if (down) { - cond = n.preds.isEmpty(); - } - - if (cond) { - - if (prev != null && next != null) { - n.crossingNumber = (prev.crossingNumber + next.crossingNumber) / 2; - } else if (prev != null) { - n.crossingNumber = prev.crossingNumber; - } else if (next != null) { - n.crossingNumber = next.crossingNumber; - } - } - } - } - - private void upSweep() { - // Upsweep - for (int i = layerCount - 2; i >= 0; i--) { - - for (LayoutNode n : layers[i]) { - n.crossingNumber = 0; - } - - for (LayoutNode n : layers[i]) { - - int count = 0; - int sum = 0; - for (LayoutEdge e : n.succs) { - int cur = e.to.x + e.relativeTo; - int factor = 1; - if (e.vip) { - factor = VIP_BONUS; - } - sum += cur*factor; - count+=factor; - } - - if (count > 0) { - sum /= count; - n.crossingNumber = sum; - } - - } - - updateCrossingNumbers(i, false); - Collections.sort(layers[i], crossingNodeComparator); - updateXOfLayer(i); - - int z = 0; - for (LayoutNode n : layers[i]) { - n.pos = z; - z++; - } - } - } - - @Override - public void postCheck() { - - HashSet visited = new HashSet<>(); - for (int i = 0; i < layers.length; i++) { - for (LayoutNode n : layers[i]) { - assert !visited.contains(n); - assert n.layer == i; - visited.add(n); - } - } - - } - } - - private class AssignYCoordinates extends AlgorithmPart { - - @Override - protected void run() { - int curY = 0; - - for (int i = 0; i < layers.length; i++) { - int maxHeight = 0; - int baseLine = 0; - int bottomBaseLine = 0; - for (LayoutNode n : layers[i]) { - maxHeight = Math.max(maxHeight, n.height - n.yOffset - n.bottomYOffset); - baseLine = Math.max(baseLine, n.yOffset); - bottomBaseLine = Math.max(bottomBaseLine, n.bottomYOffset); - } - - int maxXOffset = 0; - for (LayoutNode n : layers[i]) { - if (n.vertex == null) { - // Dummy node - n.y = curY; - n.height = maxHeight + baseLine + bottomBaseLine; - - } else { - n.y = curY + baseLine + (maxHeight - (n.height - n.yOffset - n.bottomYOffset)) / 2 - n.yOffset; - } - - for (LayoutEdge e : n.succs) { - int curXOffset = Math.abs(n.x - e.to.x); - maxXOffset = Math.max(curXOffset, maxXOffset); - } - } - - curY += maxHeight + baseLine + bottomBaseLine; - curY += layerOffset + (int) Math.sqrt(maxXOffset); - } - } - } - - private class CreateDummyNodes extends AlgorithmPart { - - private int oldNodeCount; - - @Override - protected void preCheck() { - for (LayoutNode n : nodes) { - for (LayoutEdge e : n.succs) { - assert e.from != null; - assert e.from == n; - assert e.from.layer < e.to.layer; - } - - for (LayoutEdge e : n.preds) { - assert e.to != null; - assert e.to == n; - } - } - } - - @Override - protected void run() { - oldNodeCount = nodes.size(); - - - if (combine == Combine.SAME_OUTPUTS) { - - Comparator comparator = new Comparator() { - - @Override - public int compare(LayoutEdge e1, LayoutEdge e2) { - return e1.to.layer - e2.to.layer; - } - }; - HashMap> portHash = new HashMap<>(); - ArrayList currentNodes = new ArrayList<>(nodes); - for (LayoutNode n : currentNodes) { - portHash.clear(); - - ArrayList succs = new ArrayList<>(n.succs); - HashMap topNodeHash = new HashMap<>(); - HashMap> bottomNodeHash = new HashMap<>(); - for (LayoutEdge e : succs) { - assert e.from.layer < e.to.layer; - if (e.from.layer != e.to.layer - 1) { - if (maxLayerLength != -1 && e.to.layer - e.from.layer > maxLayerLength/* && e.to.preds.size() > 1 && e.from.succs.size() > 1*/) { - assert maxLayerLength > 2; - e.to.preds.remove(e); - e.from.succs.remove(e); - - LayoutEdge topEdge = null; - - if (combine == Combine.SAME_OUTPUTS && topNodeHash.containsKey(e.relativeFrom)) { - LayoutNode topNode = topNodeHash.get(e.relativeFrom); - topEdge = new LayoutEdge(); - topEdge.relativeFrom = e.relativeFrom; - topEdge.from = e.from; - topEdge.relativeTo = topNode.width / 2; - topEdge.to = topNode; - topEdge.link = e.link; - topEdge.vip = e.vip; - e.from.succs.add(topEdge); - topNode.preds.add(topEdge); - } else { - - LayoutNode topNode = new LayoutNode(); - topNode.layer = e.from.layer + 1; - topNode.width = DUMMY_WIDTH; - topNode.height = DUMMY_HEIGHT; - nodes.add(topNode); - topEdge = new LayoutEdge(); - topEdge.relativeFrom = e.relativeFrom; - topEdge.from = e.from; - topEdge.relativeTo = topNode.width / 2; - topEdge.to = topNode; - topEdge.link = e.link; - topEdge.vip = e.vip; - e.from.succs.add(topEdge); - topNode.preds.add(topEdge); - topNodeHash.put(e.relativeFrom, topNode); - bottomNodeHash.put(e.relativeFrom, new HashMap()); - } - - HashMap hash = bottomNodeHash.get(e.relativeFrom); - - LayoutNode bottomNode = null; - if (hash.containsKey(e.to.layer)) { - bottomNode = hash.get(e.to.layer); - } else { - - bottomNode = new LayoutNode(); - bottomNode.layer = e.to.layer - 1; - bottomNode.width = DUMMY_WIDTH; - bottomNode.height = DUMMY_HEIGHT; - nodes.add(bottomNode); - hash.put(e.to.layer, bottomNode); - } - - LayoutEdge bottomEdge = new LayoutEdge(); - bottomEdge.relativeTo = e.relativeTo; - bottomEdge.to = e.to; - bottomEdge.relativeFrom = bottomNode.width / 2; - bottomEdge.from = bottomNode; - bottomEdge.link = e.link; - bottomEdge.vip = e.vip; - e.to.preds.add(bottomEdge); - bottomEdgeHash.put(topEdge, bottomEdge); - bottomNode.succs.add(bottomEdge); - - } else { - Integer i = e.relativeFrom; - if (!portHash.containsKey(i)) { - portHash.put(i, new ArrayList()); - } - portHash.get(i).add(e); - } - } - } - - succs = new ArrayList<>(n.succs); - for (LayoutEdge e : succs) { - - Integer i = e.relativeFrom; - if (portHash.containsKey(i)) { - - List list = portHash.get(i); - Collections.sort(list, comparator); - - if (list.size() == 1) { - processSingleEdge(list.get(0)); - } else { - - int maxLayer = list.get(0).to.layer; - for (LayoutEdge curEdge : list) { - maxLayer = Math.max(maxLayer, curEdge.to.layer); - } - - - int cnt = maxLayer - n.layer - 1; - LayoutEdge[] edges = new LayoutEdge[cnt]; - LayoutNode[] nodes = new LayoutNode[cnt]; - edges[0] = new LayoutEdge(); - edges[0].from = n; - edges[0].relativeFrom = i; - edges[0].vip = e.vip; - n.succs.add(edges[0]); - - nodes[0] = new LayoutNode(); - nodes[0].width = dummyWidth; - nodes[0].height = dummyHeight; - nodes[0].layer = n.layer + 1; - nodes[0].preds.add(edges[0]); - edges[0].to = nodes[0]; - edges[0].relativeTo = nodes[0].width / 2; - for (int j = 1; j < cnt; j++) { - edges[j] = new LayoutEdge(); - edges[j].vip = e.vip; - edges[j].from = nodes[j - 1]; - edges[j].relativeFrom = nodes[j - 1].width / 2; - nodes[j - 1].succs.add(edges[j]); - nodes[j] = new LayoutNode(); - nodes[j].width = dummyWidth; - nodes[j].height = dummyHeight; - nodes[j].layer = n.layer + j + 1; - nodes[j].preds.add(edges[j]); - edges[j].to = nodes[j]; - edges[j].relativeTo = nodes[j].width / 2; - } - - for (LayoutEdge curEdge : list) { - assert curEdge.to.layer - n.layer - 2 >= 0; - assert curEdge.to.layer - n.layer - 2 < cnt; - LayoutNode anchor = nodes[curEdge.to.layer - n.layer - 2]; - anchor.succs.add(curEdge); - curEdge.from = anchor; - curEdge.relativeFrom = anchor.width / 2; - n.succs.remove(curEdge); - } - - } - - portHash.remove(i); - } - } - } - } else if (combine == Combine.SAME_INPUTS) { - throw new UnsupportedOperationException("Currently not supported"); - } else { - ArrayList currentNodes = new ArrayList<>(nodes); - for (LayoutNode n : currentNodes) { - for (LayoutEdge e : n.succs) { - processSingleEdge(e); - } - } - } - } - - private void processSingleEdge(LayoutEdge e) { - LayoutNode n = e.from; - if (e.to.layer > n.layer + 1) { - LayoutEdge last = e; - for (int i = n.layer + 1; i < last.to.layer; i++) { - last = addBetween(last, i); - } - } - } - - private LayoutEdge addBetween(LayoutEdge e, int layer) { - LayoutNode n = new LayoutNode(); - n.width = dummyWidth; - n.height = dummyHeight; - n.layer = layer; - n.preds.add(e); - nodes.add(n); - LayoutEdge result = new LayoutEdge(); - result.vip = e.vip; - n.succs.add(result); - result.from = n; - result.relativeFrom = n.width / 2; - result.to = e.to; - result.relativeTo = e.relativeTo; - e.relativeTo = n.width / 2; - e.to.preds.remove(e); - e.to.preds.add(result); - e.to = n; - return result; - } - - @Override - public void printStatistics() { - System.out.println("Dummy nodes created: " + (nodes.size() - oldNodeCount)); - } - - @Override - public void postCheck() { - ArrayList currentNodes = new ArrayList<>(nodes); - for (LayoutNode n : currentNodes) { - for (LayoutEdge e : n.succs) { - assert e.from.layer == e.to.layer - 1; - } - } - - for (int i = 0; i < layers.length; i++) { - assert layers[i].size() > 0; - for (LayoutNode n : layers[i]) { - assert n.layer == i; - } - } - } - } - - private class AssignLayers extends AlgorithmPart { - - @Override - public void preCheck() { - for (LayoutNode n : nodes) { - assert n.layer == -1; - } - } - - @Override - protected void run() { - - List insertOrder = new ArrayList<>(); - - HashSet set = new HashSet<>(); - for (LayoutNode n : nodes) { - if (n.preds.size() == 0) { - set.add(n); - insertOrder.add(n); - n.layer = 0; - } - } - - int z = minLayerDifference; - HashSet newSet = new HashSet<>(); - HashSet failed = new HashSet<>(); - while (!set.isEmpty()) { - - newSet.clear(); - failed.clear(); - - for (LayoutNode n : set) { - - for (LayoutEdge se : n.succs) { - LayoutNode s = se.to; - if (!newSet.contains(s) && !failed.contains(s)) { - boolean ok = true; - for (LayoutEdge pe : s.preds) { - LayoutNode p = pe.from; - if (p.layer == -1) { - ok = false; - break; - } - } - - if (ok) { - newSet.add(s); - } else { - failed.add(s); - } - } - } - - } - - for (LayoutNode n : newSet) { - n.layer = z; - insertOrder.add(n); - } - - // Swap sets - HashSet tmp = set; - set = newSet; - newSet = tmp; - z += minLayerDifference; - } - - optimize(insertOrder); - - layerCount = z - minLayerDifference; - - for (Vertex v : lastLayerHint) { - - LayoutNode n = vertexToLayoutNode.get(v); - assert n.succs.size() == 0; - n.layer = layerCount - 1; - } - - for (Vertex v : firstLayerHint) { - LayoutNode n = vertexToLayoutNode.get(v); - assert n.preds.size() == 0; - n.layer = 0; - assert n.layer == 0; - } - } - - public void optimize(List insertOrder) { - for (int i = insertOrder.size() - 1; i >= 0; i--) { - LayoutNode cur = insertOrder.get(i); - if (cur.succs.size() > cur.preds.size()) { - int minLayer = cur.succs.get(0).to.layer; - for (LayoutEdge e : cur.succs) { - minLayer = Math.min(minLayer, e.to.layer); - } - cur.layer = minLayer - 1; - } - } - } - - @Override - public void postCheck() { - for (LayoutNode n : nodes) { - assert n.layer >= 0; - assert n.layer < layerCount; - for (LayoutEdge e : n.succs) { - assert e.from.layer < e.to.layer; - } - } - } - } - - private class ReverseEdges extends AlgorithmPart { - - private HashSet visited; - private HashSet active; - - @Override - protected void run() { - - // Remove self-edges - for (LayoutNode node : nodes) { - ArrayList succs = new ArrayList<>(node.succs); - for (LayoutEdge e : succs) { - assert e.from == node; - if (e.to == node) { - node.succs.remove(e); - node.preds.remove(e); - } - } - } - - // Reverse inputs of roots - for (LayoutNode node : nodes) { - if (node.vertex.isRoot()) { - boolean ok = true; - for (LayoutEdge e : node.preds) { - if (e.from.vertex.isRoot()) { - ok = false; - break; - } - } - if (ok) { - reverseAllInputs(node); - } - } - } - - - // Start DFS and reverse back edges - visited = new HashSet<>(); - active = new HashSet<>(); - for (LayoutNode node : nodes) { - DFS(node); - } - - - for (LayoutNode node : nodes) { - - SortedSet reversedDown = new TreeSet<>(); - - for (LayoutEdge e : node.succs) { - if (reversedLinks.contains(e.link)) { - reversedDown.add(e.relativeFrom); - } - } - - - SortedSet reversedUp = null; - if (reversedDown.size() == 0) { - reversedUp = new TreeSet<>(Collections.reverseOrder()); - } else { - reversedUp = new TreeSet<>(); - } - - for (LayoutEdge e : node.preds) { - if (reversedLinks.contains(e.link)) { - reversedUp.add(e.relativeTo); - } - } - - final int offset = X_OFFSET + DUMMY_WIDTH; - - int curX = 0; - int curWidth = node.width + reversedDown.size() * offset; - for (int pos : reversedDown) { - ArrayList reversedSuccs = new ArrayList<>(); - for (LayoutEdge e : node.succs) { - if (e.relativeFrom == pos && reversedLinks.contains(e.link)) { - reversedSuccs.add(e); - e.relativeFrom = curWidth; - } - } - - ArrayList startPoints = new ArrayList<>(); - startPoints.add(new Point(curWidth, curX)); - startPoints.add(new Point(pos, curX)); - startPoints.add(new Point(pos, reversedDown.size() * offset)); - for (LayoutEdge e : reversedSuccs) { - reversedLinkStartPoints.put(e.link, startPoints); - } - - node.inOffsets.put(pos, -curX); - curX += offset; - node.height += offset; - node.yOffset += offset; - curWidth -= offset; - } - node.width += reversedDown.size() * offset; - - if (reversedDown.size() == 0) { - curX = offset; - } else { - curX = -offset; - } - - curX = 0; - int minX = 0; - if (reversedDown.size() != 0) { - minX = -offset * reversedUp.size(); - } - - int oldNodeHeight = node.height; - for (int pos : reversedUp) { - ArrayList reversedPreds = new ArrayList<>(); - for (LayoutEdge e : node.preds) { - if (e.relativeTo == pos && reversedLinks.contains(e.link)) { - if (reversedDown.size() == 0) { - e.relativeTo = node.width + offset; - } else { - e.relativeTo = curX - offset; - } - - reversedPreds.add(e); - } - } - node.height += offset; - ArrayList endPoints = new ArrayList<>(); - - if (reversedDown.size() == 0) { - - curX += offset; - node.width += offset; - endPoints.add(new Point(node.width, node.height)); - - } else { - curX -= offset; - node.width += offset; - endPoints.add(new Point(curX, node.height)); - } - - node.outOffsets.put(pos - minX, curX); - curX += offset; - node.bottomYOffset += offset; - - - endPoints.add(new Point(pos, node.height)); - endPoints.add(new Point(pos, oldNodeHeight)); - for (LayoutEdge e : reversedPreds) { - reversedLinkEndPoints.put(e.link, endPoints); - } - } - - - if (minX < 0) { - for (LayoutEdge e : node.preds) { - e.relativeTo -= minX; - } - - for (LayoutEdge e : node.succs) { - e.relativeFrom -= minX; - } - - node.xOffset = -minX; - node.width += -minX; - } - } - - } - - private void DFS(LayoutNode startNode) { - if (visited.contains(startNode)) { - return; - } - - Stack stack = new Stack<>(); - stack.push(startNode); - - while (!stack.empty()) { - LayoutNode node = stack.pop(); - - if (visited.contains(node)) { - // Node no longer active - active.remove(node); - continue; - } - - // Repush immediately to know when no longer active - stack.push(node); - visited.add(node); - active.add(node); - - ArrayList succs = new ArrayList<>(node.succs); - for (LayoutEdge e : succs) { - if (active.contains(e.to)) { - assert visited.contains(e.to); - // Encountered back edge - reverseEdge(e); - } else if (!visited.contains(e.to) && (linksToFollow.size() == 0 || linksToFollow.contains(e.link))) { - stack.push(e.to); - } - } - } - } - - private void reverseAllInputs(LayoutNode node) { - for (LayoutEdge e : node.preds) { - assert !reversedLinks.contains(e.link); - reversedLinks.add(e.link); - node.succs.add(e); - e.from.preds.add(e); - e.from.succs.remove(e); - int oldRelativeFrom = e.relativeFrom; - int oldRelativeTo = e.relativeTo; - e.to = e.from; - e.from = node; - e.relativeFrom = oldRelativeTo; - e.relativeTo = oldRelativeFrom; - } - node.preds.clear(); - } - - private void reverseEdge(LayoutEdge e) { - assert !reversedLinks.contains(e.link); - reversedLinks.add(e.link); - - LayoutNode oldFrom = e.from; - LayoutNode oldTo = e.to; - int oldRelativeFrom = e.relativeFrom; - int oldRelativeTo = e.relativeTo; - - e.from = oldTo; - e.to = oldFrom; - e.relativeFrom = oldRelativeTo; - e.relativeTo = oldRelativeFrom; - - oldFrom.succs.remove(e); - oldFrom.preds.add(e); - oldTo.preds.remove(e); - oldTo.succs.add(e); - } - - @Override - public void postCheck() { - - for (LayoutNode n : nodes) { - - HashSet curVisited = new HashSet<>(); - Queue queue = new LinkedList<>(); - for (LayoutEdge e : n.succs) { - LayoutNode s = e.to; - queue.add(s); - curVisited.add(s); - } - - while (!queue.isEmpty()) { - LayoutNode curNode = queue.remove(); - - for (LayoutEdge e : curNode.succs) { - assert e.to != n; - if (!curVisited.contains(e.to)) { - queue.add(e.to); - curVisited.add(e.to); - } - } - } - } - } - } - private Comparator linkComparator = new Comparator() { - - @Override - public int compare(Link l1, Link l2) { - - int result = l1.getFrom().getVertex().compareTo(l2.getFrom().getVertex()); - if (result != 0) { - return result; - } - result = l1.getTo().getVertex().compareTo(l2.getTo().getVertex()); - if (result != 0) { - return result; - } - result = l1.getFrom().getRelativePosition().x - l2.getFrom().getRelativePosition().x; - if (result != 0) { - return result; - } - result = l1.getTo().getRelativePosition().x - l2.getTo().getRelativePosition().x; - return result; - } - }; - - private class BuildDatastructure extends AlgorithmPart { - - @Override - protected void run() { - // Set up nodes - List vertices = new ArrayList<>(graph.getVertices()); - Collections.sort(vertices); - - for (Vertex v : vertices) { - LayoutNode node = new LayoutNode(); - Dimension size = v.getSize(); - node.width = (int) size.getWidth(); - node.height = (int) size.getHeight(); - node.vertex = v; - nodes.add(node); - vertexToLayoutNode.put(v, node); - } - - // Set up edges - List links = new ArrayList<>(graph.getLinks()); - Collections.sort(links, linkComparator); - for (Link l : links) { - LayoutEdge edge = new LayoutEdge(); - assert vertexToLayoutNode.containsKey(l.getFrom().getVertex()); - assert vertexToLayoutNode.containsKey(l.getTo().getVertex()); - edge.from = vertexToLayoutNode.get(l.getFrom().getVertex()); - edge.to = vertexToLayoutNode.get(l.getTo().getVertex()); - edge.relativeFrom = l.getFrom().getRelativePosition().x; - edge.relativeTo = l.getTo().getRelativePosition().x; - edge.link = l; - edge.from.succs.add(edge); - edge.to.preds.add(edge); - edge.vip = l.isVIP(); - //assert edge.from != edge.to; // No self-loops allowed - } - - for (Link l : importantLinks) { - if (!vertexToLayoutNode.containsKey(l.getFrom().getVertex()) || - vertexToLayoutNode.containsKey(l.getTo().getVertex())) { - continue; - } - LayoutNode from = vertexToLayoutNode.get(l.getFrom().getVertex()); - LayoutNode to = vertexToLayoutNode.get(l.getTo().getVertex()); - for (LayoutEdge e : from.succs) { - if (e.to == to) { - linksToFollow.add(e.link); - } - } - } - } - - @Override - public void postCheck() { - - assert vertexToLayoutNode.keySet().size() == nodes.size(); - assert nodes.size() == graph.getVertices().size(); - - for (Vertex v : graph.getVertices()) { - - LayoutNode node = vertexToLayoutNode.get(v); - assert node != null; - - for (LayoutEdge e : node.succs) { - assert e.from == node; - } - - for (LayoutEdge e : node.preds) { - assert e.to == node; - } - - } - } - } - - @Override - public void doRouting(LayoutGraph graph) { - // Do nothing for now - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Node.java --- a/visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Node.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.hierarchicallayout; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public class Node { - - private N data; - private List> inEdges; - private List> outEdges; - private boolean visited; - private boolean active; - private boolean reachable; - private Graph graph; - - protected boolean isVisited() { - return visited; - } - - protected void setVisited(boolean b) { - visited = b; - } - - protected boolean isReachable() { - return reachable; - } - - protected void setReachable(boolean b) { - reachable = b; - } - - protected boolean isActive() { - return active; - } - - protected void setActive(boolean b) { - active = b; - } - - public int getInDegree() { - return getInDegree(true); - } - - public int getInDegree(boolean countSelfLoops) { - if (countSelfLoops) { - return inEdges.size(); - } else { - int cnt = 0; - for (Edge e : inEdges) { - if (e.getSource() != this) { - cnt++; - } - } - return cnt; - } - } - - public int getOutDegree() { - return outEdges.size(); - } - - protected Node(Graph graph, N data) { - setData(data); - this.graph = graph; - inEdges = new ArrayList<>(); - outEdges = new ArrayList<>(); - } - - protected void addInEdge(Edge e) { - inEdges.add(e); - } - - public Graph getGraph() { - return graph; - } - - protected void addOutEdge(Edge e) { - outEdges.add(e); - } - - protected void removeInEdge(Edge e) { - //assert inEdges.contains(e); - inEdges.remove(e); - } - - protected void removeOutEdge(Edge e) { - //assert outEdges.contains(e); - outEdges.remove(e); - } - - public List> getInEdges() { - return Collections.unmodifiableList(inEdges); - } - - public List> getOutEdges() { - return Collections.unmodifiableList(outEdges); - } - - public List> getSuccessors() { - ArrayList> succ = new ArrayList<>(); - for (Edge e : getOutEdges()) { - Node n = e.getDest(); - if (!succ.contains(n)) { - succ.add(n); - } - } - return succ; - } - - public List> getPredecessors() { - ArrayList> pred = new ArrayList<>(); - for (Edge e : getInEdges()) { - Node n = e.getSource(); - if (!pred.contains(n)) { - pred.add(n); - } - } - return pred; - } - - public N getData() { - return data; - } - - public void setData(N d) { - data = d; - } - - @Override - public String toString() { - return "Node: " + data; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Timing.java --- a/visualizer/HierarchicalLayout/src/com/sun/hotspot/igv/hierarchicallayout/Timing.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.hierarchicallayout; - -/** - * - * @author Thomas Wuerthinger - */ -public class Timing { - - private long lastValue; - private long sum; - private String name; - - public Timing(String name) { - this.name = name; - } - - @Override - public String toString() { - long val = sum; - if (lastValue != 0) { - // Timer running - long newValue = System.nanoTime(); - val += (newValue - lastValue); - } - return "Timing for " + name + " is: " + val / 1000000 + " ms"; - } - - public void print() { - System.out.println(toString()); - } - - public void start() { - lastValue = System.nanoTime(); - } - - public void stop() { - if (lastValue == 0) { - throw new IllegalStateException("You must call start before stop"); - } - long newValue = System.nanoTime(); - sum += newValue - lastValue; - lastValue = 0; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Layout/build.xml --- a/visualizer/Layout/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project com.sun.hotspot.igv.layout. - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Layout/manifest.mf --- a/visualizer/Layout/manifest.mf Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.sun.hotspot.igv.layout -OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/layout/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Layout/nbproject/build-impl.xml --- a/visualizer/Layout/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Layout/nbproject/genfiles.properties --- a/visualizer/Layout/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -build.xml.data.CRC32=cb0889d9 -build.xml.script.CRC32=d65fccb9 -build.xml.stylesheet.CRC32=79c3b980 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=cb0889d9 -nbproject/build-impl.xml.script.CRC32=7f82736d -nbproject/build-impl.xml.stylesheet.CRC32=deb65f65 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Layout/nbproject/platform.properties --- a/visualizer/Layout/nbproject/platform.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -# Deprecated since 5.0u1; for compatibility with 5.0: -disabled.clusters=\ - apisupport1,\ - harness,\ - ide8,\ - java1,\ - nb6.0,\ - profiler2 -disabled.modules=\ - org.netbeans.core.execution,\ - org.netbeans.core.multiview,\ - org.netbeans.core.output2,\ - org.netbeans.modules.applemenu,\ - org.netbeans.modules.autoupdate.services,\ - org.netbeans.modules.autoupdate.ui,\ - org.netbeans.modules.core.kit,\ - org.netbeans.modules.favorites,\ - org.netbeans.modules.javahelp,\ - org.netbeans.modules.masterfs,\ - org.netbeans.modules.options.keymap,\ - org.netbeans.modules.sendopts,\ - org.netbeans.modules.templates,\ - org.openide.compat,\ - org.openide.execution,\ - org.openide.util.enumerations -enabled.clusters=\ - platform7 -nbjdk.active=JDK_1.6 -nbplatform.active=default diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Layout/nbproject/project.properties --- a/visualizer/Layout/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -javac.source=1.7 -javac.compilerargs=-Xlint -Xlint:-serial diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Layout/nbproject/project.xml --- a/visualizer/Layout/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - com.sun.hotspot.igv.layout - - - - com.sun.hotspot.igv.layout - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Layout/nbproject/suite.properties --- a/visualizer/Layout/nbproject/suite.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -suite.dir=${basedir}/.. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Layout/src/com/sun/hotspot/igv/layout/Bundle.properties --- a/visualizer/Layout/src/com/sun/hotspot/igv/layout/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -OpenIDE-Module-Name=Layout diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutGraph.java --- a/visualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutGraph.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.layout; - -import java.util.*; - -/** - * - * @author Thomas Wuerthinger - */ -public class LayoutGraph { - - private Set links; - private SortedSet vertices; - private HashMap> inputPorts; - private HashMap> outputPorts; - private HashMap> portLinks; - - public LayoutGraph(Set links) { - this(links, new HashSet()); - } - - public LayoutGraph(Set links, Set additionalVertices) { - this.links = links; - assert verify(); - - vertices = new TreeSet<>(); - portLinks = new HashMap<>(links.size()); - inputPorts = new HashMap<>(links.size()); - outputPorts = new HashMap<>(links.size()); - - for (Link l : links) { - Port p = l.getFrom(); - Port p2 = l.getTo(); - Vertex v1 = p.getVertex(); - Vertex v2 = p2.getVertex(); - - if (!vertices.contains(v1)) { - - outputPorts.put(v1, new HashSet(1)); - inputPorts.put(v1, new HashSet(3)); - vertices.add(v1); - assert vertices.contains(v1); - } - - if (!vertices.contains(v2)) { - vertices.add(v2); - assert vertices.contains(v2); - outputPorts.put(v2, new HashSet(1)); - inputPorts.put(v2, new HashSet(3)); - } - - if (!portLinks.containsKey(p)) { - HashSet hashSet = new HashSet<>(3); - portLinks.put(p, hashSet); - } - - if (!portLinks.containsKey(p2)) { - portLinks.put(p2, new HashSet(3)); - } - - outputPorts.get(v1).add(p); - inputPorts.get(v2).add(p2); - - portLinks.get(p).add(l); - portLinks.get(p2).add(l); - } - - for (Vertex v : additionalVertices) { - if (!vertices.contains(v)) { - outputPorts.put(v, new HashSet(1)); - inputPorts.put(v, new HashSet(3)); - vertices.add(v); - vertices.contains(v); - } - } - } - - public Set getInputPorts(Vertex v) { - return this.inputPorts.get(v); - } - - public Set getOutputPorts(Vertex v) { - return this.outputPorts.get(v); - } - - public Set getPortLinks(Port p) { - return portLinks.get(p); - } - - public Set getLinks() { - return links; - } - - public boolean verify() { - return true; - } - - public SortedSet getVertices() { - return vertices; - } - - private void markNotRoot(Set notRootSet, Vertex v, Vertex startingVertex) { - - if (notRootSet.contains(v)) { - return; - } - if (v != startingVertex) { - notRootSet.add(v); - } - Set outPorts = getOutputPorts(v); - for (Port p : outPorts) { - Set portLinks = getPortLinks(p); - for (Link l : portLinks) { - Port other = l.getTo(); - Vertex otherVertex = other.getVertex(); - if (otherVertex != startingVertex) { - markNotRoot(notRootSet, otherVertex, startingVertex); - } - } - } - } - - // Returns a set of vertices with the following properties: - // - All Vertices in the set startingRoots are elements of the set. - // - When starting a DFS at every vertex in the set, every vertex of the - // whole graph is visited. - public Set findRootVertices(Set startingRoots) { - - Set notRootSet = new HashSet<>(); - for (Vertex v : startingRoots) { - if (!notRootSet.contains(v)) { - markNotRoot(notRootSet, v, v); - } - } - - Set tmpVertices = getVertices(); - for (Vertex v : tmpVertices) { - if (!notRootSet.contains(v)) { - if (this.getInputPorts(v).size() == 0) { - markNotRoot(notRootSet, v, v); - } - } - } - - for (Vertex v : tmpVertices) { - if (!notRootSet.contains(v)) { - markNotRoot(notRootSet, v, v); - } - } - - Set result = new HashSet<>(); - for (Vertex v : tmpVertices) { - if (!notRootSet.contains(v)) { - result.add(v); - } - } - assert tmpVertices.size() == 0 || result.size() > 0; - return result; - } - - public Set findRootVertices() { - return findRootVertices(new HashSet()); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutManager.java --- a/visualizer/Layout/src/com/sun/hotspot/igv/layout/LayoutManager.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.layout; - -import java.util.Set; - -/** - * - * @author Thomas Wuerthinger - */ -public interface LayoutManager { - - public void doLayout(LayoutGraph graph); - - public void doLayout(LayoutGraph graph, Set firstLayerHint, Set lastLayerHint, Set importantLinks); - - public void doRouting(LayoutGraph graph); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Layout/src/com/sun/hotspot/igv/layout/Link.java --- a/visualizer/Layout/src/com/sun/hotspot/igv/layout/Link.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.layout; - -import java.awt.Point; -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public interface Link { - - public Port getFrom(); - - public Port getTo(); - - public boolean isVIP(); - - public List getControlPoints(); - - public void setControlPoints(List list); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Layout/src/com/sun/hotspot/igv/layout/Port.java --- a/visualizer/Layout/src/com/sun/hotspot/igv/layout/Port.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.layout; - -import java.awt.Point; - -/** - * - * @author Thomas Wuerthinger - */ -public interface Port { - - public Vertex getVertex(); - - public Point getRelativePosition(); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Layout/src/com/sun/hotspot/igv/layout/Vertex.java --- a/visualizer/Layout/src/com/sun/hotspot/igv/layout/Vertex.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.layout; - -import java.awt.Dimension; -import java.awt.Point; - -/** - * - * @author Thomas Wuerthinger - */ -public interface Vertex extends Comparable { - - public Dimension getSize(); - - public Point getPosition(); - - public void setPosition(Point p); - - public boolean isRoot(); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/build.xml --- a/visualizer/LogViewer/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project com.oracle.graal.visualizer.logviewer. - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/manifest.mf --- a/visualizer/LogViewer/manifest.mf Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.oracle.graal.visualizer.logviewer -OpenIDE-Module-Layer: com/oracle/graal/visualizer/logviewer/layer.xml -OpenIDE-Module-Localizing-Bundle: com/oracle/graal/visualizer/logviewer/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/nbproject/build-impl.xml --- a/visualizer/LogViewer/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ - - - - - - - - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/nbproject/genfiles.properties --- a/visualizer/LogViewer/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -build.xml.data.CRC32=979ec129 -build.xml.script.CRC32=1c914106 -build.xml.stylesheet.CRC32=a56c6a5b@2.47.2 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=979ec129 -nbproject/build-impl.xml.script.CRC32=712ab216 -nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.2 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/nbproject/project.properties --- a/visualizer/LogViewer/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -javac.source=1.7 -javac.compilerargs=-Xlint -Xlint:-serial diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/nbproject/project.xml --- a/visualizer/LogViewer/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,146 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - com.oracle.graal.visualizer.logviewer - - - - com.oracle.graal.visualizer.editor - - - - 1.0 - - - - com.oracle.graal.visualizer.sharedactions - - - - 1.0 - - - - com.sun.hotspot.igv.data - - - - 1.0 - - - - org.eclipse.draw2d - - - - 1.0 - - - - org.jdesktop.layout - - - - 1 - 1.19.1 - - - - org.netbeans.api.visual - - - - 2.30.1 - - - - org.netbeans.modules.options.api - - - - 1 - 1.24.1 - - - - org.netbeans.modules.projectapi - - - - 1 - 1.40.1 - - - - org.openide.actions - - - - 6.24.1 - - - - org.openide.awt - - - - 7.39.1 - - - - org.openide.dialogs - - - - 7.23.1 - - - - org.openide.loaders - - - - 7.32.1 - - - - org.openide.nodes - - - - 7.25.1 - - - - org.openide.util - - - - 8.19.1 - - - - org.openide.util.lookup - - - - 8.11.1 - - - - org.openide.windows - - - - 6.39.1 - - - - - com.oracle.graal.visualizer.logviewer - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/nbproject/suite.properties --- a/visualizer/LogViewer/nbproject/suite.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -suite.dir=${basedir}/.. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/META-INF/services/com.oracle.graal.visualizer.editor.CompilationViewerFactory --- a/visualizer/LogViewer/src/META-INF/services/com.oracle.graal.visualizer.editor.CompilationViewerFactory Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -com.oracle.graal.visualizer.logviewer.LogCompilationViewerFactory \ No newline at end of file diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/Bundle.properties --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -OpenIDE-Module-Name=LogViewer diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/LogCompilationViewer.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/LogCompilationViewer.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer; - -import com.oracle.graal.visualizer.logviewer.scene.LogScene; -import com.oracle.graal.visualizer.editor.CompilationViewer; -import com.sun.hotspot.igv.data.InputGraph; -import java.awt.Component; -import org.openide.util.Lookup; -import org.openide.util.lookup.Lookups; - -class LogCompilationViewer implements CompilationViewer { - - private LogScene scene; - - public LogCompilationViewer() { - this.scene = new LogScene(); - } - - @Override - public Lookup getLookup() { - return Lookups.fixed(); - } - - @Override - public Component getComponent() { - return scene; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/LogCompilationViewerFactory.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/LogCompilationViewerFactory.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer; - -import com.oracle.graal.visualizer.editor.CompilationViewer; -import com.oracle.graal.visualizer.editor.SplitCompilationViewerFactory; -import com.sun.hotspot.igv.data.InputGraph; - -public class LogCompilationViewerFactory extends SplitCompilationViewerFactory { - - @Override - public String getName() { - return "Log"; - } - - @Override - protected CompilationViewer createViewer(InputGraph graph) { - return new LogCompilationViewer(); - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/layer.xml --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/layer.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/LogLine.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/LogLine.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.model; - -public class LogLine { - - private final int lineNum; - private final CharSequence text; - private final Method method; - private final Scope scope; - private final Node node; - - LogLine(int lineNum, CharSequence text, Method method, Scope scope, Node node) { - this.lineNum = lineNum; - this.text = text; - this.method = method; - this.scope = scope; - this.node = node; - } - - /** - * Returns the number of the line in the log file - * @return file line number - */ - public int getLineNumber() { - return lineNum; - } - - /** - * Returns the text of the log line - * @return log line text - */ - public String getText() { - return text.toString(); - } - - /** - * Returns the parent method - * @return the parent method - */ - public Method getMethod() { - return method; - } - - /** - * Returns the parent scope - * @return the parent scope - */ - public Scope getScope() { - return scope; - } - - /** - * Returns the parent node - * @return the parent node (or null if the log is not in a node's context) - */ - public Node getNode() { - return node; - } - - /** - * The string representation of a log line is the text of it. - */ - @Override - public String toString() { - return getText(); - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/LogModel.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/LogModel.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.model; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.NoSuchElementException; - -public class LogModel { - - private List methods = new ArrayList<>(); - private List logs = new ArrayList<>(); - - void add(Method method) { - methods.add(method); - } - - /** - * Returns a list of all methods within the log model. - * @return list of methods - */ - public List getMethods() { - return Collections.unmodifiableList(methods); - } - - void add(LogLine log) { - logs.add(log); - } - - /** - * Returns a list of all logs - * @return list of log lines - */ - public List getLogs() { - return Collections.unmodifiableList(logs); - } - - /** - * Returns a list of logs which are before and after a specific log line (and the line itself). - * @param log reference log line - * @param pre number of lines before the reference line - * @param post number of lines after the reference line - * @return list of log lines (size: pre + post + 1) - */ - public List range(LogLine log, int pre, int post) { - if(log == null) throw new NoSuchElementException(); - - List logs = getLogs(); - int index = logs.indexOf(log); - - if(index == -1) throw new NoSuchElementException(); - - int fromIndex = index - pre; - int toIndex = index + post + 1; - - return getLogs().subList(fromIndex > 0 ? fromIndex : 0, toIndex < logs.size() ? toIndex : logs.size()); - } - - /** - * Returns a string with log l which are before and after a specific log line (and the line itself). - * @param log reference log line - * @param pre number of lines before the reference line - * @param post number of lines after the reference line - * @return list of log lines (size: pre + post + 1) - */ - public String rangeAsString(LogLine log, int pre, int post) { - List list = range(log, pre, post); - - String ls = System.getProperty("line.separator"); - - boolean first = true; - StringBuilder buf = new StringBuilder(); - for(LogLine line : list) { - if(!first) buf.append(ls); - else first = false; - - buf.append(line); - } - - return buf.toString(); - } - - public LogLine getLogLine(int lineNum) { - int index = lineNum; - if(index >= logs.size()) index = logs.size()-1; - - LogLine logLine = logs.get(lineNum); - while(logLine.getLineNumber() > lineNum) { - logLine = logs.get(--index); - } - while(logLine.getLineNumber() < lineNum) { - logLine = logs.get(++index); - } - - return logLine; - } - - public List range(int lineNum, int pre, int post) { - LogLine logLine = getLogLine(lineNum); - return range(logLine, pre, post); - } - - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/LogParser.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/LogParser.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,230 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.model; - -import com.oracle.graal.visualizer.logviewer.model.io.FileLine; -import com.oracle.graal.visualizer.logviewer.model.io.ProgressMonitor; -import com.oracle.graal.visualizer.logviewer.model.io.SeekableFile; -import com.oracle.graal.visualizer.logviewer.model.io.SeekableFileReader; -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class LogParser { - - private static final Pattern METHOD_PATTERN = - Pattern.compile("Finished target method HotSpotMethod<(.+?)>, isStub (true|false)"); - private static final Pattern SCOPE_PATTERN = - Pattern.compile("scope: (.+?)"); - private static final Pattern NODE_PATTERN = - Pattern.compile(".*?([0-9]+)\\|([0-9a-zA-Z.]+).*?"); - - private final List errorListeners = new ArrayList<>(); - private final List errors = new ArrayList<>(); - - /** - * Parses a log file without any feedback. When the parsing process is finished, the method returns a LogModel-object. - * @param file log file - * @return model-object - * @throws IOException - * @throws LogParserException - */ - public LogModel parse(File file) throws IOException { - return parse(file, null); - } - - /** - * Parses a log file and uses a ProgressMonitor to give the caller a progress feedback. It returns a LogModel-object. - * @param file log file - * @param monitor monitor for progress monitoring (uses default gap) - * @return model-object - * @throws IOException - * @throws LogParserException - */ - public LogModel parse(File file, ProgressMonitor monitor) throws IOException { - return parse(file, monitor, SeekableFileReader.DEFAULT_GAP); - } - - /** - * Parses a log file and uses a ProgressMonitor to give the caller a progress feedback. It returns a LogModel-object. - * @param file log file - * @param monitor monitor for progress monitoring (uses custom gap) - * @param gap custom gap (every x bytes read from the file, the monitor will be informed) - * @return model-object - * @throws IOException - * @throws LogParserException - */ - public LogModel parse(File file, ProgressMonitor monitor, int gap) throws IOException { - errors.clear(); - SeekableFileReader reader = new SeekableFileReader(file, monitor, gap); - SeekableFile seekableFile = reader.getSeekableFile(); - BufferedReader r = new BufferedReader(reader); - - LogModel model = new LogModel(); - Method currentMethod = new Method(model); - Scope currentScope = null; - - Matcher matcher; - boolean methodNameSet = false; - - int lineNum = -1; - String line; - while((line = r.readLine()) != null) { - lineNum++; - - methodNameSet = false; - - matcher = SCOPE_PATTERN.matcher(line); - if(matcher.matches()) { - String name = matcher.group(1); - currentScope = new Scope(name, currentMethod); - currentMethod.add(currentScope); - } - - matcher = METHOD_PATTERN.matcher(line); - boolean methodPatternMatches = matcher.matches(); - - if(methodPatternMatches){ - currentScope = null; - String name = matcher.group(1); - boolean isStub = Boolean.parseBoolean(matcher.group(2)); - currentMethod.init(name, isStub); - model.add(currentMethod); - methodNameSet = true; - } - - Node currentNode = null; - matcher = NODE_PATTERN.matcher(line); - if(matcher.matches()) { - if(currentScope == null){ - raiseError(lineNum, line, "scope is missing"); - continue; - } - int number = Integer.parseInt(matcher.group(1)); - currentNode = currentScope.getNode(number); - if(currentNode == null) { - String name = matcher.group(2); - currentNode = new Node(number, name, currentScope); - currentScope.add(currentNode); - } - } - - FileLine fileLine = seekableFile.get(lineNum); - LogLine log = new LogLine(lineNum, fileLine, currentMethod, currentScope, currentNode); - if(currentNode != null) currentNode.add(log); - if(currentScope != null) currentScope.add(log); - currentMethod.add(log); - model.add(log); - - if(methodPatternMatches) { - currentMethod = new Method(model); - } - } - - if(!methodNameSet) raiseError(lineNum, line, "unexpected end of stream"); - - return model; - } - - private void raiseError(int lineNum, String line, String message) { - ParseError error = new ParseError(lineNum, line, message); - errors.add(error); - for(ParseErrorListener listener : errorListeners) { - listener.errorOccurred(error); - } - } - - /** - * Adds a ParseErrorListener to the listeners - * @param listener - */ - public void addParseErrorListener(ParseErrorListener listener) { - errorListeners.add(listener); - } - - public void removeParseErrorListener(ParseErrorListener listener) { - errorListeners.remove(listener); - } - - /** - * Checks if errors occurred during the parsing process - * @return true if there are errors stored, false otherwise - */ - public boolean hasErrors() { - return !errors.isEmpty(); - } - - /** - * Returns a list of all errors. - * @return error list - */ - public List getErrors() { - return Collections.unmodifiableList(errors); - } - - public static class ParseError { - - private final int lineNum; - private final String line; - private final String message; - - private ParseError(int lineNum, String line, String message) { - this.lineNum = lineNum; - this.message = message; - this.line = line; - } - - public int getLineNumber() { - return lineNum; - } - - public String getLine() { - return line; - } - - public String getMessage() { - return message; - } - - } - - public static interface ParseErrorListener { - - /** - * Called when a new error occurs.

- * Attention: This method runs on the same thread as the parsing process. - * If time-consuming tasks should be executed, please consider multithreading. - * @param error - */ - public void errorOccurred(ParseError error); - - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/Method.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/Method.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.model; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class Method { - - private String name; - private boolean isStub; - private final LogModel model; - private List scopes = new ArrayList<>(); - private List logs = new ArrayList<>(); - - Method(LogModel model) { - name = null; - isStub = false; - this.model = model; - } - - void init(String name, boolean isStub) { - this.name = name; - this.isStub = isStub; - } - - /** - * Returns the name of the method - * @return the method name - */ - public String getName() { - return name; - } - - /** - * Returns true if this is a stub method. - * @return true if is stub, false otherwise - */ - public boolean isStub() { - return isStub; - } - - /** - * Returns the model which holds this method. - * @return model-object - */ - public LogModel getModel() { - return model; - } - - void add(Scope scope) { - scopes.add(scope); - } - - /** - * Returns a list of all scopes inside a target method. - * @return list of scopes - */ - public List getScopes() { - return scopes; - } - - void add(LogLine log) { - logs.add(log); - } - - /** - * Returns a list of all logs in the context of the method. - * @return list of log lines - */ - public List getLogs() { - return Collections.unmodifiableList(logs); - } - - /** - * The string representation of a method is its name. - */ - @Override - public String toString() { - return getName(); - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/Node.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/Node.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.model; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class Node { - - private final int number; - private final String name; - private final Scope scope; - private List logs = new ArrayList<>(); - - - Node(int number, String name, Scope scope) { - this.number = number; - this.name = name; - this.scope = scope; - } - - /** - * Returns the node number. - * @return the node number - */ - public int getNumber() { - return number; - } - - /** - * Returns the node name. - * @return the node name - */ - public String getName() { - return name; - } - - /** - * Returns the parent scope. - * @return the parent scope - */ - public Scope getScope() { - return scope; - } - - void add(LogLine log) { - logs.add(log); - } - - /** - * Returns a list of all logs within a nodes context. - * @return list of log lines - */ - public List getLogs() { - return Collections.unmodifiableList(logs); - } - - /** - * The string represenation of a node is "<name> (<number>)". - */ - @Override - public String toString() { - return getName() + "(" + getNumber() + ")"; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/Scope.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/Scope.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.model; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class Scope { - - private final String name; - private final Method method; - private List nodes = new ArrayList<>(); - private List logs = new ArrayList<>(); - - Scope(String name, Method method) { - this.name = name; - this.method = method; - } - - /** - * Returns the scope name. - * @return the scope name - */ - public String getName() { - return name; - } - - /** - * Returns the parent method. - * @return the parent method - */ - public Method getMethod() { - return method; - } - - void add(Node node) { - nodes.add(node); - } - - /** - * Returns a list of all node-objects inside a scope. - * @return list of nodes - */ - public List getNodes() { - return Collections.unmodifiableList(nodes); - } - - void add(LogLine log) { - logs.add(log); - } - - /** - * Returns a list of all logs inside a scope. - * @return list of log lines - */ - public List getLogs() { - return logs; - } - - /** - * Returns the node inside a scope with the given number. - * @param number node number - * @return node-object - */ - public Node getNode(int number) { - for(Node node : nodes) { - if(node.getNumber() == number) return node; - } - return null; - } - - /** - * The string representation of a scope is its name. - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return getName(); - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/Filter.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/Filter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.model.filter; - -import com.oracle.graal.visualizer.logviewer.model.LogLine; - -public interface Filter { - - /** - * Sets the constraints for a filter.
- * They can be every type of objects. In general these are strings, but it can also be - * a Integer (like in the NodeFilter):
- * Filter nodeFilter = filterManager.getNodeFilter(); - * filter.setConstraints((String)nodeName, (Integer)nodeNumber); - * @param constraints filter constraints - */ - void setConstraints(Object ... constraints); - - /** - * Indicates whether to keep a log line in the filter results, or not. - * @param line log line which should be checked - * @return true if the line should be kept, false otherwise - */ - boolean keep(LogLine line); - - /** - * Activates or deactivates a filter. Deactivated filters will be ignored. - * @param active true to activate, false to deactivate - */ - void setActive(boolean active); - - /** - * Returns the activation status - * @return true for an active filter, false otherwise - */ - boolean isActive(); - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/FilterManager.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/FilterManager.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.model.filter; - -import com.oracle.graal.visualizer.logviewer.model.LogLine; -import com.oracle.graal.visualizer.logviewer.model.LogModel; -import java.util.ArrayList; -import java.util.List; - -public class FilterManager { - - private final List filters = new ArrayList<>(); - private final Filter methodFilter, scopeFilter, nodeFilter, fulltextFilter; - - /** - * Creates a new instance of the filter manager. - */ - public FilterManager() { - add(methodFilter = new MethodFilter()); - add(scopeFilter = new ScopeFilter()); - add(nodeFilter = new NodeFilter()); - add(fulltextFilter = new FullTextFilter()); - } - - /** - * Executes a filtering process with the given log model as subject. Inactive filters will be ignored. - * @param model subject - * @return filtered list of log lines - * @throws InterruptedException - */ - public List execute(LogModel model) throws InterruptedException { - List input = model.getLogs(); - List output = new ArrayList<>(); - - for(LogLine line : input) { - if(Thread.interrupted()) throw new InterruptedException(); - if(keep(line)) output.add(line); - } - - if(Thread.interrupted()) throw new InterruptedException(); - - return output; - } - - private boolean keep(LogLine line) { - boolean keep = true; - for(Filter filter : filters) { - keep = keep && (!filter.isActive() || filter.keep(line)); - } - return keep; - } - - private Filter add(Filter filter) { - filters.add(filter); - return filter; - } - - /** - * Returns the instance of a method filter - * @return method filter - */ - public Filter getMethodFilter() { - return methodFilter; - } - - /** - * Returns the instance of a scope filter - * @return scope filter - */ - public Filter getScopeFilter() { - return scopeFilter; - } - - /** - * Returns the instance of a node filter - * @return node filter - */ - public Filter getNodeFilter() { - return nodeFilter; - } - - /** - * Returns the instance of a full text filter - * @return full text filter - */ - public Filter getFullTextFilter() { - return fulltextFilter; - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/FullTextFilter.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/FullTextFilter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.model.filter; - -import com.oracle.graal.visualizer.logviewer.model.LogLine; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -class FullTextFilter implements Filter { - - private Pattern p; - private boolean active = true; - - @Override - public void setConstraints(Object ... constraints) { - this.p = null; - for(Object constraint : constraints) { - setConstraint(constraint); - } - } - - private void setConstraint(Object constraint) { - if(constraint instanceof String) { - if(((String)constraint).trim().length() > 0) { - this.p = Pattern.compile((String)constraint); - } - else { - this.p = null; - } - } - } - - @Override - public boolean keep(LogLine line) { - if(p == null) return true; - - Matcher matcher = p.matcher(line.getText()); - return matcher.find(); - } - - @Override - public void setActive(boolean active) { - this.active = active; - } - - @Override - public boolean isActive() { - return active; - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/MethodFilter.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/MethodFilter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.model.filter; - -import com.oracle.graal.visualizer.logviewer.model.LogLine; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -class MethodFilter implements Filter { - - private Pattern p; - private boolean active = true; - - @Override - public void setConstraints(Object ... constraints) { - this.p = null; - for(Object constraint : constraints) { - setConstraint(constraint); - } - } - - private void setConstraint(Object constraint) { - if(constraint instanceof String) { - if(((String)constraint).trim().length() > 0) { - this.p = Pattern.compile((String)constraint); - } - else { - this.p = null; - } - } - } - - @Override - public boolean keep(LogLine line) { - if(p == null) return true; - - Matcher matcher = p.matcher(line.getMethod().getName()); - return matcher.find(); - } - - @Override - public void setActive(boolean active) { - this.active = active; - } - - @Override - public boolean isActive() { - return active; - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/NodeFilter.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/NodeFilter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.model.filter; - -import com.oracle.graal.visualizer.logviewer.model.LogLine; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -class NodeFilter implements Filter { - - private Pattern p; - private Integer nodeNum; - private boolean active = true; - - @Override - public void setConstraints(Object ... constraints) { - this.nodeNum = null; - this.p = null; - for(Object constraint : constraints) { - setConstraint(constraint); - } - } - - private void setConstraint(Object constraint) { - if(constraint instanceof String) { - - if(((String)constraint).trim().length() > 0) { - this.p = Pattern.compile((String)constraint); - } - else { - this.p = null; - } - } - else if(constraint instanceof Integer) { - this.nodeNum = (Integer)constraint; - } - - } - - @Override - public boolean keep(LogLine line) { - if(p == null && nodeNum == null) return true; - - if(line.getNode() == null) return false; - - boolean keep = false; - - if(p != null) { - Matcher matcher = p.matcher(line.getNode().getName()); - keep = keep || matcher.find(); - } - if(nodeNum != null) { - keep = keep || nodeNum.equals(line.getNode().getNumber()); - } - - return keep; - } - - @Override - public void setActive(boolean active) { - this.active = active; - } - - @Override - public boolean isActive() { - return active; - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/ScopeFilter.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/filter/ScopeFilter.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.model.filter; - -import com.oracle.graal.visualizer.logviewer.model.LogLine; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -class ScopeFilter implements Filter { - - private Pattern p; - private boolean active = true; - - @Override - public void setConstraints(Object ... constraints) { - this.p = null; - for(Object constraint : constraints) { - setConstraint(constraint); - } - } - - private void setConstraint(Object constraint) { - if(constraint instanceof String) { - if(((String)constraint).trim().length() > 0) { - this.p = Pattern.compile((String)constraint); - } - else { - this.p = null; - } - } - } - - @Override - public boolean keep(LogLine line) { - if(p == null) return true; - - if(line.getScope() == null) return false; - - Matcher matcher = p.matcher(line.getScope().getName()); - return matcher.find(); - } - - @Override - public void setActive(boolean active) { - this.active = active; - } - - @Override - public boolean isActive() { - return active; - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/io/FileLine.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/io/FileLine.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.model.io; - -import java.io.IOException; -import java.lang.ref.WeakReference; - -public class FileLine implements CharSequence { - - private final SeekableFile seekableFile; - private WeakReference cache; - public final long off; - public final int len; - - public FileLine(SeekableFile seekableFile, long off, int len) { - this.seekableFile = seekableFile; - this.off = off; - this.len = len; - } - - @Override - public String toString() { - String line = null; - - if(cache != null) line = cache.get(); - - if(line == null) { - try { - line = seekableFile.read(this); - cache = new WeakReference<>(line); - } catch (IOException e) { - e.printStackTrace(); - } - } - - return line; - } - - @Override - public int length() { - return len; - } - - @Override - public char charAt(int index) { - String line = toString(); - return line != null ? line.charAt(index) : 0; - } - - @Override - public CharSequence subSequence(int start, int end) { - String line = toString(); - return line != null ? line.subSequence(start, end) : ""; - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/io/ProgressMonitor.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/io/ProgressMonitor.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.model.io; - -public interface ProgressMonitor { - - /** - * Triggered when some work has been done.

- * Attention: This method runs on the same thread as the reading process. - * If time-consuming tasks should be executed, please consider multithreading. - * @param percentage Value in range between 0 and 1 to indicate how much work has been done. - */ - public void worked(float percentage); - - /** - * Triggered when work is done completely.

- * Attention: This method runs on the same thread as the reading process. - * If time-consuming tasks should be executed, please consider multithreading. - */ - public void finished(); - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/io/SeekableFile.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/io/SeekableFile.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.model.io; - -import java.io.*; -import java.util.ArrayList; -import java.util.List; - -public class SeekableFile implements Closeable { - - private final RandomAccessFile raf; - private List lines = new ArrayList<>(); - - SeekableFile(File file) throws FileNotFoundException { - raf = new RandomAccessFile(file, "r"); - } - - void addLine(long off, int len) { - lines.add(new FileLine(this, off, len)); - } - - public int size() { - return lines.size(); - } - - public FileLine get(int lineNum) throws IOException { - FileLine line = lines.get(lineNum); - return line; - } - - String read(FileLine line) throws IOException { - if(line == null) throw new IllegalArgumentException("line is null"); - raf.seek(line.off); - - byte [] buf = new byte[line.len]; - - if(raf.read(buf) != line.len) throw new IOException("error while reading line"); - - return new String(buf); - } - - @Override - public void close() throws IOException { - raf.close(); - } - - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/io/SeekableFileReader.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/model/io/SeekableFileReader.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.model.io; - -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.Reader; - -public class SeekableFileReader extends Reader { - - public static final int DEFAULT_GAP = 1024; // in bytes - - private final FileReader reader; - private SeekableFile seekableFile; - private ProgressMonitor monitor; - private long filelen; - private int gap; - - public SeekableFileReader(File file) throws IOException { - super(file); - reader = new FileReader(file); - seekableFile = new SeekableFile(file); - } - - public SeekableFileReader(File file, ProgressMonitor monitor, int gap) throws IOException { - this(file); - this.monitor = monitor; - this.filelen = file.length(); - this.gap = gap; - } - - public SeekableFileReader(File file, ProgressMonitor monitor) throws IOException { - this(file, monitor, DEFAULT_GAP); - } - - public SeekableFile getSeekableFile() { - return seekableFile; - } - - @Override - public void close() throws IOException { - reader.close(); - } - - private long bytes = 0; - private boolean skipLF = false; - private long off; - private long lastGapped = 0; - private boolean finished = false; - - @Override - public int read(char[] cbuf, int offset, int length) throws IOException { - - int l = reader.read(cbuf, offset, length); - - if(l == -1 && !finished) { - seekableFile.addLine(off, (int)(bytes-off)); - finished = true; - if(monitor != null) { - monitor.worked(1); - monitor.finished(); - } - } - - for(int i = 0; i < l; ++i) { - Character ch = new Character(cbuf[i]); - int chlen = ch.toString().getBytes(reader.getEncoding()).length; - - if(skipLF && ch != '\n') { - seekableFile.addLine(off, (int)(bytes-off-chlen)); - off = bytes; - skipLF = false; - } - - bytes += chlen; - - if(monitor != null) { - if(bytes > lastGapped+gap) { - lastGapped = bytes; - monitor.worked(((float)bytes)/((float)filelen)); - } - } - - if(ch == '\r') { - skipLF = true; - } - if(ch == '\n') { - seekableFile.addLine(off, (int)(bytes-off-(skipLF ? 2*chlen : chlen))); - off = bytes; - skipLF = false; - } - } - - return l; - } - - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/BookmarkDialog.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/BookmarkDialog.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.scene; - -import com.oracle.graal.visualizer.logviewer.model.LogLine; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.GridLayout; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.List; -import javax.swing.*; - -public class BookmarkDialog extends JDialog { - - private JList lstBookmarks; - private List logLines; - - public BookmarkDialog(List bookmarks, Window parent) { - super(parent, JDialog.ModalityType.APPLICATION_MODAL); - - this.logLines = bookmarks; - - DefaultListModel mdlBookmarks = new DefaultListModel(); - lstBookmarks = new JList(mdlBookmarks); - JScrollPane jspBookmarks = new JScrollPane(lstBookmarks); - - for (LogLine bookmark : bookmarks) { - mdlBookmarks.addElement(bookmark.getLineNumber() + ": Method " + bookmark.getMethod() + " - Scope " + bookmark.getScope() + " - " + bookmark.getText()); - } - - JButton btnOk = new JButton("Go to"); - JButton btnCancel = new JButton("Cancel"); - - // init listeners - lstBookmarks.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - close(); - } - } - }); - - btnOk.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent ae) { - if (lstBookmarks.isSelectionEmpty()) - return; - close(); - } - }); - btnCancel.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent ae) { - lstBookmarks.clearSelection(); - close(); - } - }); - - // build layout - JPanel pnlButtons = new JPanel(); - - pnlButtons.setLayout(new GridLayout(1, 2)); - pnlButtons.add(btnOk); - pnlButtons.add(btnCancel); - - this.setLayout(new BorderLayout()); - this.add(jspBookmarks, BorderLayout.CENTER); - this.add(pnlButtons, BorderLayout.SOUTH); - - this.pack(); - this.setMinimumSize(new Dimension(600, this.getPreferredSize().height)); - this.setLocationRelativeTo(parent); - this.setResizable(false); - this.setVisible(true); - } - - public LogLine getTarget() { - if (lstBookmarks.isSelectionEmpty()) - return null; - return logLines.get(lstBookmarks.getSelectedIndex()); - } - - private void close() { - this.setVisible(false); - this.dispose(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/BookmarkableLogViewer.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/BookmarkableLogViewer.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,378 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.scene; - -import com.oracle.graal.visualizer.logviewer.model.LogLine; -import java.awt.*; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextPane; -import javax.swing.text.BadLocationException; -import javax.swing.text.DefaultHighlighter; -import javax.swing.text.Highlighter; -import javax.swing.text.JTextComponent; -import org.openide.util.Exceptions; - -public class BookmarkableLogViewer extends JPanel { - - private static final Color BOOKMARK_COLOR = Color.CYAN; - - private static final Highlighter.HighlightPainter BOOKMARK_PAINTER = - new DefaultHighlighter.DefaultHighlightPainter(BOOKMARK_COLOR); - - private JTextPane txpText; - private JTextPane txpLines; - private Highlighter textHighlighter; - private Highlighter lineHighlighter; - private FontMetrics fm; - private Map bookmarks = new TreeMap<>(); - private List logLines = new ArrayList<>(); - - public BookmarkableLogViewer() { - init(); - } - - private void init() { - txpText = new JTextPane(); - txpLines = new JTextPane(); - - // needed for correct layouting - Insets ins = txpLines.getInsets(); - txpLines.setMargin(new Insets(ins.top + 1, ins.left, ins.bottom, ins.right)); - - textHighlighter = new BookmarkHighlighter(); - lineHighlighter = new BookmarkHighlighter(); - - txpText.setHighlighter(textHighlighter); - //txpText.setMinimumSize(new Dimension(100, 100)); - txpText.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12)); - txpText.setEditable(false); - - txpLines.setHighlighter(lineHighlighter); - txpLines.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12)); - txpLines.setBackground(Color.LIGHT_GRAY); - txpLines.setEnabled(false); - txpLines.setForeground(Color.BLACK); - txpLines.addMouseListener(mouseInputListener); - - fm = txpText.getFontMetrics(txpText.getFont()); - - JPanel pnlBookmarks = new JPanel(); - pnlBookmarks.setLayout(new BorderLayout()); - pnlBookmarks.add(txpText, BorderLayout.CENTER); - - JScrollPane jspBookmarks = new JScrollPane(pnlBookmarks); - jspBookmarks.setRowHeaderView(txpLines); - jspBookmarks.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); - jspBookmarks.getVerticalScrollBar().setUnitIncrement(15); - - this.setLayout(new BorderLayout()); - this.add(jspBookmarks, BorderLayout.CENTER); - } - - public int getCurrentlyDisplayedTopLine() { - Rectangle view = txpText.getVisibleRect(); - return getAbsoluteLine((int) Math.ceil(view.y/fm.getHeight())); - } - - public int getCurrentTopLine() { - return logLines.get(0).getLineNumber(); - } - - public int getCurrentBottomLine() { - return logLines.get(logLines.size()-1).getLineNumber(); - } - - public void clearLogLines() { - this.logLines = new ArrayList<>(); - txpText.setText(""); - txpLines.setText(""); - clearHighlighter(); - } - - public void setLogLines(List logLines) { - this.logLines = logLines; - - clearHighlighter(); - clearLineNumbers(); - String text = ""; - for (int i = 0; i < logLines.size(); i++) { - text += logLines.get(i).getText(); - if (i < logLines.size() - 1) { - text += "\n"; - } - } - txpText.setText(text); - setLineNumbers(); - - txpText.setCaretPosition(0); - txpLines.setCaretPosition(0); - - for (int bookmark : bookmarks.keySet()) { - if (bookmark < logLines.get(0).getLineNumber()) { - continue; - } - if (bookmark > logLines.get(logLines.size() - 1).getLineNumber()) { - break; - } - - int line = getRelativeLine(bookmark); - - addHighlight(logLines.get(line)); - } - } - - public void setLogLines(List logLines, int focus) { - setLogLines(logLines); - - //does not work for some reason - jtextpane jumps to caret position afterwards - //moveToBookmark(focus); - - //workaround - set caret position bevore moving - Rectangle visible = txpText.getVisibleRect(); - int visibleLines = (int)(Math.ceil(visible.height/fm.getHeight())); - - String text = txpText.getText(); - int line = logLines.get(0).getLineNumber(); - for (int i = 0; i < text.length(); i++) { - if (text.charAt(i) == '\n') - line++; - if (line == focus+visibleLines || i == text.length() - 1) { - txpText.setCaretPosition(i); - break; - } - } - moveToBookmark(focus); - } - - public List getBookmarkedLines() { - List lines = new ArrayList<>(); - for (int bookmark : bookmarks.keySet()) { - lines.add(bookmarks.get(bookmark).logLine); - } - return lines; - } - - public int tryLastBookmark() { - int line = getCurrentlyDisplayedTopLine(); - - int firstShownLine = getCurrentTopLine(); - - int bookmarkKey = -1; - for (int key : bookmarks.keySet()) { - if (key >= line) { - break; - } - - bookmarkKey = key; - } - - if (bookmarkKey >= firstShownLine) { - moveToBookmark(bookmarkKey); - return -1; - } - - return bookmarkKey; - } - - public int tryNextBookmark() { - Rectangle visible = txpText.getVisibleRect(); - int lastLine = (int) Math.floor((visible.y + visible.height) / fm.getHeight()); - lastLine = getAbsoluteLine(lastLine); - - int lastShownLine = getCurrentBottomLine(); - - int bookmarkKey = -1; - for (int key : bookmarks.keySet()) { - if (key > lastLine) { - bookmarkKey = key; - break; - } - if (key > lastShownLine) { - break; - } - } - - if (bookmarkKey > 0 && bookmarkKey <= lastShownLine) { - moveToBookmark(bookmarkKey); - return -1; - } - - return bookmarkKey; - } - - private void moveToBookmark(int line) { - int relLine = getRelativeLine(line); - Rectangle visible = txpText.getVisibleRect(); - Rectangle position = new Rectangle(0, relLine * fm.getHeight(), visible.width, visible.height); - txpText.scrollRectToVisible(position); - } - - private int getAbsoluteLine(int line) { - return logLines.get(0).getLineNumber() + line; - } - - private int getRelativeLine(int line) { - return line - logLines.get(0).getLineNumber(); - } - - private int getStartOffset(JTextComponent component, int line) { - return component.getDocument().getDefaultRootElement().getElement(line).getStartOffset(); - } - - private int getEndOffset(JTextComponent component, int line) { - return component.getDocument().getDefaultRootElement().getElement(line).getEndOffset(); - } - - private void addHighlight(LogLine logLine) { - try { - int line = logLine.getLineNumber(); - int relativeLine = getRelativeLine(line); - - Object hl1 = textHighlighter.addHighlight(getStartOffset(txpText, relativeLine), getEndOffset(txpText, relativeLine), BOOKMARK_PAINTER); - Object hl2 = lineHighlighter.addHighlight(getStartOffset(txpLines, relativeLine), getEndOffset(txpLines, relativeLine), BOOKMARK_PAINTER); - bookmarks.put(line, new Bookmark(logLine, hl1, hl2)); - } catch (BadLocationException ex) { - Exceptions.printStackTrace(ex); - } - } - - private void removeHighlight(int line) { - int abs = getAbsoluteLine(line); - Bookmark bookmark = bookmarks.get(abs); - textHighlighter.removeHighlight(bookmark.hl1); - lineHighlighter.removeHighlight(bookmark.hl2); - bookmarks.remove(abs); - } - - public void clearBookmarks() { - bookmarks = new TreeMap<>(); - clearHighlighter(); - } - - private void clearHighlighter() { - textHighlighter.removeAllHighlights(); - lineHighlighter.removeAllHighlights(); - } - - private void clearLineNumbers() { - txpLines.setText(""); - } - - private void setLineNumbers() { - clearLineNumbers(); - - if (logLines.isEmpty()) { - return; - } - - int colCnt = String.valueOf(logLines.get(logLines.size() - 1).getLineNumber()).length() + 2; - - int firstNr = logLines.get(0).getLineNumber(); - String text = String.format("%" + colCnt + "s", firstNr + " "); - for (int i = 1; i < logLines.size(); i++) { - text += "\n"; - text += String.format("%" + colCnt + "s", (firstNr + i) + " "); - } - txpLines.setText(text); - } - - private MouseListener mouseInputListener = new MouseAdapter() { - - @Override - public void mouseClicked(MouseEvent me) { - if (txpLines.getText().length() == 0) { - return; - } - if (me.getClickCount() == 2) { - int caretPos = txpLines.getCaretPosition(); - - int lineOffset = txpLines.getDocument().getDefaultRootElement().getElementIndex(caretPos); - if (txpLines.getText().charAt(caretPos - 1) == '\n') { - lineOffset--; - } - - if (bookmarks.containsKey(getAbsoluteLine(lineOffset))) { - removeHighlight(lineOffset); - } else { - addHighlight(logLines.get(lineOffset)); - } - } - } - }; - - class Bookmark { - - public final LogLine logLine; - public final Object hl1; - public final Object hl2; - - public Bookmark(LogLine logLine, Object hl1, Object hl2) { - this.logLine = logLine; - this.hl1 = hl1; - this.hl2 = hl2; - } - } - - class BookmarkHighlighter extends DefaultHighlighter { - - private JTextComponent component; - - @Override - public void install(JTextComponent component) { - super.install(component); - this.component = component; - } - - @Override - public void deinstall(JTextComponent component) { - super.deinstall(component); - this.component = null; - } - - @Override - public void paint(Graphics g) { - Highlighter.Highlight[] highlights = getHighlights(); - - for (int i = 0; i < highlights.length; i++) { - Highlighter.Highlight hl = highlights[i]; - Rectangle bg = component.getBounds(); - Insets insets = component.getInsets(); - bg.x = insets.left; - bg.y = insets.top; - bg.height = insets.top + insets.bottom; - Highlighter.HighlightPainter painter = hl.getPainter(); - painter.paint(g, hl.getStartOffset(), hl.getEndOffset(), bg, component); - } - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/ImportLogErrorDialog.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/ImportLogErrorDialog.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.scene; - -import com.oracle.graal.visualizer.logviewer.model.LogParser; -import java.awt.Component; -import java.util.List; -import javax.swing.JOptionPane; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; - -public class ImportLogErrorDialog { - - public static void showDialog(Component parent, List errors) { - JTextArea txaErrors = new JTextArea(); - - for (LogParser.ParseError error : errors) { - txaErrors.append("Error at line " + error.getLineNumber()); - txaErrors.append(": " + error.getMessage()); - txaErrors.append("\n"); - txaErrors.append("Log line: " + error.getLine()); - txaErrors.append("\n"); - } - - JScrollPane scpErrors = new JScrollPane(txaErrors); - - JOptionPane.showMessageDialog(parent, scpErrors, "Parse errors", JOptionPane.ERROR_MESSAGE); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/LogScene.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/LogScene.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,671 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.scene; - -import com.oracle.graal.visualizer.logviewer.model.LogLine; -import com.oracle.graal.visualizer.logviewer.model.LogModel; -import com.oracle.graal.visualizer.logviewer.model.LogParser; -import com.oracle.graal.visualizer.logviewer.model.filter.Filter; -import com.oracle.graal.visualizer.logviewer.model.filter.FilterManager; -import com.oracle.graal.visualizer.logviewer.model.io.ProgressMonitor; -import com.oracle.graal.visualizer.logviewer.scene.model.LogTableModel; -import com.oracle.graal.visualizer.logviewer.scene.model.TableLine; -import java.awt.*; -import java.awt.event.*; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Timer; -import java.util.TimerTask; -import java.util.regex.PatternSyntaxException; -import javax.swing.*; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import javax.swing.table.TableCellRenderer; -import javax.swing.table.TableColumn; -import org.openide.util.Exceptions; -import org.openide.util.NbPreferences; -import sun.awt.CausedFocusEvent; - -public class LogScene extends JPanel { - private static final String PREFERENCE_DIR = "dir"; - - private static final String ICON_PREFIX = "/com/oracle/graal/visualizer/logviewer/scene/icons/"; - private static final String ICON_ARROW_DOWN = ICON_PREFIX + "arrow_down.png"; - private static final String ICON_ARROW_UP = ICON_PREFIX + "arrow_up.png"; - private static final String ICON_BOOKMARK_BACK = ICON_PREFIX + "bookmark_back.png"; - private static final String ICON_BOOKMARK_FWD = ICON_PREFIX + "bookmark_forward.png"; - private static final String ICON_BOOKMARK_LIST = ICON_PREFIX + "bookmark_list.png"; - private static final String ICON_LOAD = ICON_PREFIX + "loading.gif"; - - private static final ImageIcon IMGICON_LOAD = new ImageIcon(LogScene.class.getResource(ICON_LOAD)); - - private static final int LOG_LINES = 50; - private static final int KEYSTROKE_RATE = 100; // rate at which the keystrokes are checked - private static final int KEYSTROKE_TRESHOLD = 400; // time in ms after which a search is triggered - - private FilterManager filterManager; - private Thread filterRunThread; - - private int timeSinceLastKeystroke = -1; - - private JLabel lblMessage; - private JLabel lblIcon; - - private JLabel lblMethodFilter; - private JLabel lblScopeFilter; - private JLabel lblNodeFilter; - private JLabel lblFulltextFilter; - private JTextField txfMethodFilter; - private JTextField txfScopeFilter; - private JTextField txfNodeFilter; - private JTextField txfFulltextFilter; - - private JTable tblResult; - private LogTableModel tblResultModel; - - private BookmarkableLogViewer logViewer; - private JButton btnBookmarkBack; - private JButton btnBookmarkFwd; - private JButton btnBookmarkList; - private JButton btnLoadMoreUp; - private JButton btnLoadMoreDown; - - private LogParser parser = new LogParser(); - private LogModel logModel = null; - private LogStatus logStatus = LogStatus.NO_LOG; - - private static LogScene instance; - - private enum LogStatus { - NO_LOG, LOADING, ACTIVE - } - - public static LogScene getInstance() { - return instance; - } - - public LogScene() { - initComponents(); - } - - private void initComponents() { - filterManager = new FilterManager(); - - lblMessage = new JLabel("No logfile loaded."); - lblIcon = new JLabel(""); - - // Initialize filter components - lblMethodFilter = new JLabel("Target Method:"); - lblScopeFilter = new JLabel("Scope:"); - lblNodeFilter = new JLabel("Node:"); - lblFulltextFilter = new JLabel("Fulltext:"); - - txfMethodFilter = new JTextField(); - txfScopeFilter = new JTextField(); - txfNodeFilter = new JTextField(); - txfFulltextFilter = new JTextField(); - - tblResultModel = new LogTableModel(); - tblResult = new JTable(tblResultModel); - tblResult.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - tblResult.getTableHeader().setReorderingAllowed(false); - tblResult.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); - - Dimension dim = tblResult.getPreferredScrollableViewportSize(); - tblResult.setPreferredScrollableViewportSize(new Dimension(dim.width, 10*tblResult.getRowHeight() + tblResult.getTableHeader().getHeight())); - JScrollPane scpTblResult = new JScrollPane(tblResult); - scpTblResult.setMinimumSize(new Dimension(dim.width, 10*tblResult.getRowHeight() + tblResult.getTableHeader().getHeight())); - - logViewer = new BookmarkableLogViewer(); - - btnLoadMoreUp = new JButton(new ImageIcon(LogScene.class.getResource(ICON_ARROW_UP))); - btnLoadMoreDown = new JButton(new ImageIcon(LogScene.class.getResource(ICON_ARROW_DOWN))); - - btnLoadMoreUp.setFocusable(false); - btnLoadMoreUp.setToolTipText("Load more previous log lines"); - - btnLoadMoreDown.setFocusable(false); - btnLoadMoreDown.setToolTipText("Load more following log lines"); - - btnBookmarkBack = new JButton(new ImageIcon(LogScene.class.getResource(ICON_BOOKMARK_BACK))); - btnBookmarkList = new JButton(new ImageIcon(LogScene.class.getResource(ICON_BOOKMARK_LIST))); - btnBookmarkFwd = new JButton(new ImageIcon(LogScene.class.getResource(ICON_BOOKMARK_FWD))); - - btnBookmarkBack.setFocusable(false); - btnBookmarkBack.setToolTipText("Navigate to the last bookmark."); - - btnBookmarkFwd.setFocusable(false); - btnBookmarkFwd.setToolTipText("Navigate to the next bookmark."); - - btnBookmarkList.setFocusable(false); - btnBookmarkList.setToolTipText("List all known bookmarks."); - - JPanel pnl = new JPanel(); - pnl.setLayout(new GridBagLayout()); - pnl.setOpaque(false); - - JPanel logViewerPanel = new JPanel(); - logViewerPanel.setLayout(new GridBagLayout()); - logViewerPanel.setOpaque(false); - - JPanel messagePanel = new JPanel(); - messagePanel.setLayout(new BoxLayout(messagePanel, BoxLayout.LINE_AXIS)); - messagePanel.setOpaque(false); - - // Initialize Listeners - initListeners(); - - // Layout components - GridBagConstraints gbc = new GridBagConstraints(); - - messagePanel.add(lblMessage); - messagePanel.add(Box.createHorizontalGlue()); - messagePanel.add(lblIcon); - - Insets standardInsets = gbc.insets; - - gbc.gridx = 0; - gbc.gridy = 0; - gbc.anchor = GridBagConstraints.WEST; - gbc.fill = GridBagConstraints.HORIZONTAL; - gbc.weightx = 1; - gbc.weighty = 0; - gbc.gridwidth = 2; - gbc.insets = new Insets(2, 0, 2, 0); - pnl.add(messagePanel, gbc); - - gbc.fill = GridBagConstraints.NONE; - gbc.gridwidth = 1; - gbc.weightx = 0; - gbc.weighty = 0; - gbc.gridy++; - gbc.insets = standardInsets; - pnl.add(lblMethodFilter, gbc); - - gbc.gridy++; - pnl.add(lblScopeFilter, gbc); - - gbc.gridy++; - pnl.add(lblNodeFilter, gbc); - - gbc.gridy++; - pnl.add(lblFulltextFilter, gbc); - - gbc.gridx++; - gbc.gridy = 1; - gbc.fill = GridBagConstraints.HORIZONTAL; - gbc.weightx = 0.75; - pnl.add(txfMethodFilter, gbc); - - gbc.gridy++; - pnl.add(txfScopeFilter, gbc); - - gbc.gridy++; - pnl.add(txfNodeFilter, gbc); - - gbc.gridy++; - pnl.add(txfFulltextFilter, gbc); - - gbc.gridx = 0; - //gbc.gridy++; - gbc.gridwidth = 2; - gbc.weightx = 1; - gbc.anchor = GridBagConstraints.FIRST_LINE_START; - //pnl.add(btnSearch, gbc); - - gbc.gridy++; - pnl.add(scpTblResult, gbc); - - gbc.gridy++; - gbc.weighty = 1; - gbc.fill = GridBagConstraints.BOTH; - pnl.add(logViewerPanel, gbc); - - gbc = new GridBagConstraints(); - gbc.gridx = 0; - gbc.gridy = 0; - gbc.gridheight = 6; - gbc.weightx = 1; - gbc.weighty = 1; - gbc.fill = GridBagConstraints.BOTH; - logViewerPanel.add(logViewer, gbc); - - gbc.gridx++; - gbc.weightx = 0; - gbc.weighty = 0; - gbc.fill = GridBagConstraints.NONE; - gbc.anchor = GridBagConstraints.PAGE_START; - gbc.gridheight = 1; - logViewerPanel.add(btnLoadMoreUp, gbc); - - gbc.gridy++; - logViewerPanel.add(btnLoadMoreDown, gbc); - - gbc.gridy++; - logViewerPanel.add(Box.createRigidArea(btnLoadMoreUp.getSize())); - - gbc.gridy++; - logViewerPanel.add(btnBookmarkBack, gbc); - - gbc.gridy++; - logViewerPanel.add(btnBookmarkFwd, gbc); - - gbc.gridy++; - logViewerPanel.add(btnBookmarkList, gbc); - - this.setLayout(new BorderLayout()); - this.add(pnl, BorderLayout.CENTER); - - Timer keyTimer = new Timer(); - keyTimer.scheduleAtFixedRate(new KeystrokeTimer(), KEYSTROKE_RATE, KEYSTROKE_RATE); - - LogScene.instance = this; - } - - private void initListeners() { - txfMethodFilter.addKeyListener(new FilterKeyListener()); - txfScopeFilter.addKeyListener(new FilterKeyListener()); - txfNodeFilter.addKeyListener(new FilterKeyListener()); - txfFulltextFilter.addKeyListener(new FilterKeyListener()); - - txfMethodFilter.addFocusListener(new FilterFocusListener()); - txfScopeFilter.addFocusListener(new FilterFocusListener()); - txfNodeFilter.addFocusListener(new FilterFocusListener()); - txfFulltextFilter.addFocusListener(new FilterFocusListener()); - - btnLoadMoreUp.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent ae) { - int line = logViewer.getCurrentlyDisplayedTopLine(); - int top = logViewer.getCurrentTopLine(); - int bottom = logViewer.getCurrentBottomLine(); - logViewer.setLogLines(logModel.range(line, line - top + LOG_LINES, bottom - line), line); - } - }); - - btnLoadMoreDown.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent ae) { - int line = logViewer.getCurrentlyDisplayedTopLine(); - int top = logViewer.getCurrentTopLine(); - int bottom = logViewer.getCurrentBottomLine(); - logViewer.setLogLines(logModel.range(line, line - top, bottom - line + LOG_LINES), line); - } - }); - - btnBookmarkBack.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent ae) { - int result = logViewer.tryLastBookmark(); - if (result >= 0) { - tblResult.clearSelection(); - logViewer.setLogLines(logModel.range(result, LOG_LINES, LOG_LINES), result); - } - } - }); - - btnBookmarkFwd.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent ae) { - int result = logViewer.tryNextBookmark(); - if (result >= 0) { - tblResult.clearSelection(); - logViewer.setLogLines(logModel.range(result, LOG_LINES, LOG_LINES), result); - } - } - }); - - btnBookmarkList.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent ae) { - List bookmarkedLines = logViewer.getBookmarkedLines(); - if (bookmarkedLines.size() > 0) { - BookmarkDialog bd = new BookmarkDialog(bookmarkedLines, null); - if (bd.getTarget() != null) { - LogLine target = bd.getTarget(); - int line = target.getLineNumber(); - logViewer.setLogLines(logModel.range(line, LOG_LINES, LOG_LINES), line); - } - } else { - JOptionPane.showMessageDialog(LogScene.this, "No bookmarks set.", "", JOptionPane.INFORMATION_MESSAGE); - } - } - }); - - tblResult.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent lse) { - if (tblResult.getSelectedRow() == -1) { - logViewer.clearLogLines(); - return; - } - - TableLine selectedLine = tblResultModel.getTableLine(tblResult.getSelectedRow()); - int firstLine = selectedLine.getFirstLine(); - int lastLine = selectedLine.getLastLine(); - - if (firstLine == lastLine) { - // only display selected line - List line = new ArrayList<>(); - line.add(selectedLine.getLogLine()); - logViewer.setLogLines(line); - } else { - // display selected range - int pre = firstLine==lastLine?LOG_LINES:selectedLine.getLogLine().getLineNumber()-firstLine; - int post = firstLine==lastLine?LOG_LINES:lastLine-selectedLine.getLogLine().getLineNumber(); - - logViewer.setLogLines(logModel.range(selectedLine.getLogLine(), pre, post)); - } - } - }); - } - - private boolean executeFilters() { - if (logStatus == LogStatus.NO_LOG) { - loadLogFile(); - return false; - } - if (logStatus == LogStatus.LOADING) { - return false; - } - - boolean execute = trySetFilter(filterManager.getMethodFilter(), txfMethodFilter.getText().trim(), lblMethodFilter); - execute = trySetFilter(filterManager.getScopeFilter(), txfScopeFilter.getText().trim(), lblScopeFilter) || execute; - try { - // node number - int node = Integer.parseInt(txfNodeFilter.getText().trim()); - execute = trySetFilter(filterManager.getNodeFilter(), node, lblNodeFilter) || execute; - } catch (Exception e) { - // node name - execute = trySetFilter(filterManager.getNodeFilter(), txfNodeFilter.getText().trim(), lblNodeFilter) || execute; - } - execute = trySetFilter(filterManager.getFullTextFilter(), txfFulltextFilter.getText().trim(), lblFulltextFilter) || execute; - - if (!execute) - return true; - - tryInterruptFilter(); - - filterRunThread = new Thread(new Runnable() { - - @Override - public void run() { - try { - List result = filterManager.execute(logModel); - lblIcon.setIcon(null); - - if (!Thread.interrupted()) - buildTableEntries(result); - } catch (InterruptedException e) { - } - } - - }); - lblIcon.setIcon(IMGICON_LOAD); - filterRunThread.start(); - - return true; - } - - private boolean trySetFilter(Filter filter, Object constraint, JLabel marker) { - try { - filter.setConstraints(constraint); - marker.setForeground(Color.BLACK); - return constraint != null && (!(constraint instanceof String) || (constraint instanceof String && ((String)constraint).trim().length() > 0)); - } catch (PatternSyntaxException e) { - filter.setConstraints(new Object[]{}); - marker.setForeground(Color.RED); - return false; - } - } - - private void tryInterruptFilter() { - if (filterRunThread != null && (filterRunThread.isAlive() || !filterRunThread.isInterrupted())) { - lblIcon.setIcon(null); - filterRunThread.interrupt(); - } - } - - private void buildTableEntries(List filterResult) { - List tableEntries; - - int methodLength = txfMethodFilter.getText().trim().length(); - int scopeLength = txfScopeFilter.getText().trim().length(); - int nodeLength = txfNodeFilter.getText().trim().length(); - int fulltextLength = txfFulltextFilter.getText().trim().length(); - - boolean preventGrouping = nodeLength != 0 || fulltextLength != 0; - - if (!preventGrouping && methodLength > 0 && scopeLength == 0) { - tableEntries = groupByMethod(filterResult); - } else if (!preventGrouping && scopeLength > 0) { - tableEntries = groupByScope(filterResult); - } else { - tableEntries = showAllLines(filterResult); - } - - tblResultModel.setLogEntries(tableEntries); - - int width = 0; - for (int i = 0; i < tableEntries.size(); i++) { - TableCellRenderer tcr = tblResult.getCellRenderer(i, 0); - Component c = tcr.getTableCellRendererComponent(tblResult, tblResultModel.getValueAt(i, 0), false, false, i, 0); - if (c instanceof JLabel) { - JLabel l = (JLabel) c; - FontMetrics fm = l.getFontMetrics(l.getFont()); - width = Math.max(width, fm.stringWidth(l.getText())); - } - } - - // proper resizing of column - // setWidth and setPreferredWidth do not trigger resize - TableColumn col = tblResult.getColumnModel().getColumn(0); - col.setMinWidth(width+5); - col.setMaxWidth(width+5); - - // reenable resizing for user - col.setMinWidth(0); - col.setMaxWidth(999); - } - - private List groupByMethod(List filterResult) { - List tableEntries = new ArrayList<>(); - int firstLine = -1; - for (int i = 0; i < filterResult.size(); i++) { - LogLine line = filterResult.get(i); - - if (firstLine < 0) - firstLine = line.getLineNumber(); - - if (i < filterResult.size() - 1) { - LogLine next = filterResult.get(i+1); - if (line.getMethod() != next.getMethod()) { - tableEntries.add(new TableLine(line, firstLine)); - firstLine = next.getLineNumber(); - } - } else { - tableEntries.add(new TableLine(line, firstLine)); - } - } - return tableEntries; - } - - private List groupByScope(List filterResult) { - List tableEntries = new ArrayList<>(); - LogLine firstScopeLine = null; - for (int i = 0; i < filterResult.size(); i++) { - LogLine line = filterResult.get(i); - - if (firstScopeLine == null) - firstScopeLine = line; - - if (i < filterResult.size() - 1) { - LogLine next = filterResult.get(i+1); - if (line.getScope() != next.getScope()) { - tableEntries.add(new TableLine(firstScopeLine, line.getLineNumber())); - firstScopeLine = next; - } - } else { - tableEntries.add(new TableLine(firstScopeLine, line.getLineNumber())); - } - } - return tableEntries; - } - - private List showAllLines(List filterResult) { - List tableEntries = new ArrayList<>(); - for (LogLine line : filterResult) { - tableEntries.add(new TableLine(line)); - } - return tableEntries; - } - - public void loadLogFile() { - JFileChooser fc = new JFileChooser(); - fc.setFileFilter(new javax.swing.filechooser.FileFilter() { - - @Override - public boolean accept(File f) { - return f.isDirectory() || - f.getName().toLowerCase().endsWith(".txt") || - f.getName().toLowerCase().endsWith(".log"); - } - - @Override - public String getDescription() { - return "Log files (*.txt, *.log)"; - } - }); - fc.setCurrentDirectory(new File(NbPreferences.forModule(LogScene.class).get(PREFERENCE_DIR, "~"))); - fc.setDialogTitle("Load log file"); - - if (fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { - tryInterruptFilter(); - - final File file = fc.getSelectedFile(); - - NbPreferences.forModule(LogScene.class).put(PREFERENCE_DIR, file.getParent()); - - lblIcon.setIcon(IMGICON_LOAD); - logStatus = LogStatus.LOADING; - new Thread(new Runnable(){ - - @Override - public void run() { - try { - logModel = parser.parse(file, new LoadProgressMonitor(lblMessage, "Loading file " + file.getName() + "...")); - lblIcon.setIcon(null); - lblMessage.setText("Current logfile: " + file.getName()); - logStatus = LogStatus.ACTIVE; - } catch (IOException ex) { - Exceptions.printStackTrace(ex); - } - } - - }).start(); - } - } - - private class FilterKeyListener extends KeyAdapter { - @Override - public void keyTyped(KeyEvent e) { - tryInterruptFilter(); - timeSinceLastKeystroke = 0; - } - } - - private class FilterFocusListener implements FocusListener { - private boolean ignore = false; - - @Override - public void focusGained(FocusEvent fe) { - if (!ignore && logStatus == LogStatus.NO_LOG) { - ignore = true; - loadLogFile(); - } - } - - @Override - public void focusLost(FocusEvent fe) { - if (fe instanceof CausedFocusEvent) { - CausedFocusEvent cfe = (CausedFocusEvent) fe; - ignore = ignore && // don't change ignore to true if it is already false - cfe.getCause() == CausedFocusEvent.Cause.ACTIVATION; // ACTIVATION is triggered if the - // FileChooser is opened - } - } - - } - - private class KeystrokeTimer extends TimerTask { - @Override - public void run() { - if (timeSinceLastKeystroke < 0) - return; - - timeSinceLastKeystroke += KEYSTROKE_RATE; - - if (timeSinceLastKeystroke >= KEYSTROKE_TRESHOLD) { - int save = timeSinceLastKeystroke; - timeSinceLastKeystroke = -1; // needs to be set to -1 to prevent - // multiple parallel filter execution - - if (!executeFilters()) - timeSinceLastKeystroke = save; - } - } - } - - private class LoadProgressMonitor implements ProgressMonitor { - private String staticText; - private JLabel lblStatus; - - public LoadProgressMonitor(JLabel lblStatus, String staticText) { - this.lblStatus = lblStatus; - this.staticText = staticText; - - lblStatus.setText(staticText); - } - - @Override - public void worked(float percentage) { - int perc = Math.round(percentage*100); - lblStatus.setText(staticText + " (" + perc + " %)"); - } - - @Override - public void finished() { - if (parser.hasErrors()) { - if (JOptionPane.showConfirmDialog(LogScene.this, "Parsing log file finished with errors. Show error messages?", "Warning", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) { - List errors = parser.getErrors(); - ImportLogErrorDialog.showDialog(LogScene.this, errors); - } - } - } - - }; -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/actions/ImportLogAction.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/actions/ImportLogAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.scene.actions; - -import com.oracle.graal.visualizer.logviewer.scene.LogScene; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.awt.ActionRegistration; - -@ActionID(id = "com.oracle.graal.visualizer.logviewer.scene.actions.ImportLogActions", category = "File") -@ActionRegistration(displayName = "Import Log", iconBase = "com/oracle/graal/visualizer/logviewer/scene/icons/import_log.png") -@ActionReference(path = "Menu/File", position = 600) -public class ImportLogAction implements ActionListener { - - @Override - public void actionPerformed(ActionEvent ae) { - LogScene.getInstance().loadLogFile(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/arrow_down.png Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/arrow_down.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/arrow_up.png Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/arrow_up.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/bookmark_back.png Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/bookmark_back.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/bookmark_forward.png Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/bookmark_forward.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/bookmark_list.png Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/bookmark_list.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/import_log.png Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/import_log.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/loading.gif Binary file visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/icons/loading.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/model/LogTableModel.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/model/LogTableModel.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.scene.model; - -import java.util.ArrayList; -import java.util.List; -import javax.swing.table.AbstractTableModel; - -public class LogTableModel extends AbstractTableModel { - private final static String[] columnNames = {"Line #", "Method", "Scope", "Node", "Log Text"}; - - private List entries = new ArrayList<>(); - - public void setLogEntries(List entries) { - this.entries = entries; - fireTableDataChanged(); - } - - public TableLine getTableLine(int line) { - return entries.get(line); - } - - @Override - public int getRowCount() { - return entries.size(); - } - - @Override - public int getColumnCount() { - return columnNames.length; - } - - @Override - public String getColumnName(int column) { - return columnNames[column]; - } - - @Override - public Object getValueAt(int i, int i1) { - switch (i1) { - case 0: - return entries.get(i).getLineNr(); - case 1: - return entries.get(i).getLogLine().getMethod().getName(); - case 2: - return entries.get(i).getLogLine().getScope()!=null? - entries.get(i).getLogLine().getScope().getName():""; - case 3: - return entries.get(i).getLogLine().getNode()!=null? - entries.get(i).getLogLine().getNode().getName():""; - case 4: - return entries.get(i).getLogLine().getText(); - } - return null; - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/model/TableLine.java --- a/visualizer/LogViewer/src/com/oracle/graal/visualizer/logviewer/scene/model/TableLine.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.logviewer.scene.model; - -import com.oracle.graal.visualizer.logviewer.model.LogLine; - -public class TableLine { - - private int lineNr; - private LogLine logLine; - - // display single log line - public TableLine(LogLine logLine) { - this(logLine, logLine.getLineNumber()); - } - - // display line number range (from logLine to lineNr or vice versa) - public TableLine(LogLine logLine, int lineNr) { - this.logLine = logLine; - this.lineNr = lineNr; - } - - public int getFirstLine() { - return lineNr < logLine.getLineNumber()?lineNr:logLine.getLineNumber(); - } - - public int getLastLine() { - return lineNr > logLine.getLineNumber()?lineNr:logLine.getLineNumber(); - } - - public String getLineNr() { - if (lineNr == logLine.getLineNumber()) { - return String.valueOf(lineNr); - } - return getFirstLine() + "-" + getLastLine(); - } - - public LogLine getLogLine() { - return logLine; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/build.xml --- a/visualizer/OutlineView/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project com.oracle.graal.visualizer.outline. - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/manifest.mf --- a/visualizer/OutlineView/manifest.mf Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.oracle.graal.visualizer.outline -OpenIDE-Module-Layer: com/oracle/graal/visualizer/outline/layer.xml -OpenIDE-Module-Localizing-Bundle: com/oracle/graal/visualizer/outline/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/nbproject/build-impl.xml --- a/visualizer/OutlineView/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/nbproject/genfiles.properties --- a/visualizer/OutlineView/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -build.xml.data.CRC32=077de97c -build.xml.script.CRC32=d29d586c -build.xml.stylesheet.CRC32=79c3b980 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=077de97c -nbproject/build-impl.xml.script.CRC32=03daa42d -nbproject/build-impl.xml.stylesheet.CRC32=deb65f65 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/nbproject/platform.properties --- a/visualizer/OutlineView/nbproject/platform.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -# Deprecated since 5.0u1; for compatibility with 5.0: -disabled.clusters=\ - apisupport1,\ - harness,\ - ide8,\ - java1,\ - nb6.0,\ - profiler2 -disabled.modules=\ - org.netbeans.core.execution,\ - org.netbeans.core.multiview,\ - org.netbeans.core.output2,\ - org.netbeans.modules.applemenu,\ - org.netbeans.modules.autoupdate.services,\ - org.netbeans.modules.autoupdate.ui,\ - org.netbeans.modules.core.kit,\ - org.netbeans.modules.favorites,\ - org.netbeans.modules.javahelp,\ - org.netbeans.modules.masterfs,\ - org.netbeans.modules.options.keymap,\ - org.netbeans.modules.sendopts,\ - org.netbeans.modules.templates,\ - org.openide.compat,\ - org.openide.execution,\ - org.openide.util.enumerations -enabled.clusters=\ - platform7 -nbjdk.active=JDK_1.6 -nbplatform.active=default diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/nbproject/project.properties --- a/visualizer/OutlineView/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -javac.source=1.7 -javac.compilerargs=-Xlint -Xlint:-serial diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/nbproject/project.xml --- a/visualizer/OutlineView/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,144 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - com.oracle.graal.visualizer.outline - - - - at.ssw.visualizer.cfg - - - - 1.0 - - - - com.sun.hotspot.igv.data - - - - 1.0 - - - - com.sun.hotspot.igv.difference - - - - 1.0 - - - - com.sun.hotspot.igv.settings - - - - 1.0 - - - - com.sun.hotspot.igv.util - - - - 1.0 - - - - org.netbeans.api.progress - - - - 1 - 1.23.1 - - - - org.openide.actions - - - - 6.21.1 - - - - org.openide.awt - - - - 7.30.1 - - - - org.openide.dialogs - - - - 7.18.1 - - - - org.openide.explorer - - - - 6.34.1 - - - - org.openide.filesystems - - - - 7.46.1 - - - - org.openide.loaders - - - - 7.20.1 - - - - org.openide.nodes - - - - 7.20.1 - - - - org.openide.util - - - - 8.14.1 - - - - org.openide.util.lookup - - - - 8.6.1 - - - - org.openide.windows - - - - 6.39.1 - - - - - com.oracle.graal.visualizer.outline - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/nbproject/suite.properties --- a/visualizer/OutlineView/nbproject/suite.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -suite.dir=${basedir}/.. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/Bundle.properties --- a/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -AdvancedOption_DisplayName_Coordinator=Settings -AdvancedOption_Tooltip_Coordinator=Visualization Tool Settings -CTL_OutlineTopComponent=Outline -HINT_OutlineTopComponent=Displays loaded compilations. -OpenIDE-Module-Name=OutlineView diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/CompilationNode.java --- a/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/CompilationNode.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.oracle.graal.visualizer.outline; - -import com.sun.hotspot.igv.data.*; -import com.sun.hotspot.igv.data.services.GraphViewer; -import java.awt.Image; -import java.util.ArrayList; -import java.util.List; -import javax.swing.Action; -import javax.swing.JOptionPane; -import org.openide.actions.OpenAction; -import org.openide.cookies.OpenCookie; -import org.openide.nodes.AbstractNode; -import org.openide.nodes.Children; -import org.openide.nodes.Node; -import org.openide.util.ImageUtilities; -import org.openide.util.Lookup; -import org.openide.util.lookup.AbstractLookup; -import org.openide.util.lookup.InstanceContent; -import org.openide.util.lookup.Lookups; - -public class CompilationNode extends AbstractNode implements ChangedListener { - - private CompilationNode(final Folder folder, Children children, InstanceContent content) { - super(children, new AbstractLookup(content)); - this.setDisplayName(folder.getName()); - - if (folder instanceof Group) { - content.add(new OpenCookie() { - - @Override - public void open() { - final List graphs = ((Group) folder).getGraphs(); - if (graphs.isEmpty()) { - JOptionPane.showMessageDialog(null, "Cannot open compilation, because there was no snapshots recorded!"); - } else { - Lookup.getDefault().lookup(GraphViewer.class).view(graphs.get(0)); - } - } - }); - } - content.add(folder); - folder.getChangedEvent().addListener(this); - } - - @Override - public void changed(Object folder) { - if (this.getChildren() == Children.LEAF) { - setChildren(createFolderChildren((Folder) folder)); - this.fireIconChange(); - } - } - - private static class FolderChildren extends Children.Keys { - - private final Folder folder; - - public FolderChildren(Folder folder) { - this.folder = folder; - folder.getChangedEvent().addListener(changedListener); - } - - @Override - protected Node[] createNodes(Folder e) { - return new Node[]{new CompilationNode(e)}; - } - - @Override - public void addNotify() { - List result = new ArrayList<>(); - for (FolderElement o : folder.getElements()) { - if (o instanceof Folder) { - result.add((Folder) o); - } - } - this.setKeys(result); - } - private final ChangedListener changedListener = new ChangedListener() { - - @Override - public void changed(Object source) { - addNotify(); - } - }; - } - - @Override - public Image getIcon(int i) { - if (this.getChildren() == Children.LEAF) { - return ImageUtilities.loadImage("com/oracle/graal/visualizer/outline/images/leaf_node.gif"); - } else { - return ImageUtilities.loadImage("com/oracle/graal/visualizer/outline/images/node.gif"); - } - } - - protected CompilationNode(Folder folder) { - this(folder, createFolderChildren(folder), new InstanceContent()); - } - - private static Children createFolderChildren(Folder folder) { - for (FolderElement elem : folder.getElements()) { - if (elem instanceof Folder) { - return new FolderChildren(folder); - } - } - return Children.LEAF; - } - - @Override - public Action[] getActions(boolean context) { - List actions = new ArrayList<>(); - actions.add((Action) OpenAction.findObject(OpenAction.class, true)); - actions.addAll(Lookups.forPath(OutlineTopComponent.NODE_ACTIONS_FOLDER).lookupAll(Action.class)); - return actions.toArray(new Action[actions.size()]); - } - - @Override - public Action getPreferredAction() { - return (Action) OpenAction.findObject(OpenAction.class, true); - } - - @Override - public Image getOpenedIcon(int i) { - return getIcon(i); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/OutlineTopComponent.form --- a/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/OutlineTopComponent.form Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/OutlineTopComponent.java --- a/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/OutlineTopComponent.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.oracle.graal.visualizer.outline; - -import com.oracle.graal.visualizer.outline.server.ServerPanel; -import com.oracle.graal.visualizer.util.LookupUtils; -import com.sun.hotspot.igv.data.GraphDocument; -import java.awt.BorderLayout; -import javax.swing.Action; -import org.openide.actions.GarbageCollectAction; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.awt.Toolbar; -import org.openide.explorer.ExplorerManager; -import org.openide.explorer.ExplorerUtils; -import org.openide.explorer.view.BeanTreeView; -import org.openide.util.NbBundle; -import org.openide.windows.TopComponent; -import org.openide.windows.WindowManager; - -@TopComponent.Description(preferredID = OutlineTopComponent.PREFERRED_ID, persistenceType = TopComponent.PERSISTENCE_ALWAYS) -@TopComponent.Registration(mode = "explorer", openAtStartup = true) -@ActionID(category = "Window", id = "com.oracle.graal.visualizer.outline.OutlineTopComponent") -@ActionReference(path = "Menu/Window") -@TopComponent.OpenActionRegistration(displayName = "Outline", preferredID = OutlineTopComponent.PREFERRED_ID) -public final class OutlineTopComponent extends TopComponent implements ExplorerManager.Provider { - - public static final String GLOBAL_ACTIONS_FOLDER = "Actions/Outline/Global"; - public static final String NODE_ACTIONS_FOLDER = "Actions/Outline/Nodes"; - public static OutlineTopComponent instance; - public static final String PREFERRED_ID = "OutlineTopComponent"; - private ExplorerManager manager; - private GraphDocument document; - - private OutlineTopComponent() { - initComponents(); - - setName(NbBundle.getMessage(OutlineTopComponent.class, "CTL_OutlineTopComponent")); - setToolTipText(NbBundle.getMessage(OutlineTopComponent.class, "HINT_OutlineTopComponent")); - - document = new GraphDocument(); - initListView(); - initToolbar(); - } - - private void initListView() { - manager = new ExplorerManager(); - manager.setRootContext(new CompilationNode(document)); - ((BeanTreeView) this.treeView).setRootVisible(false); - associateLookup(ExplorerUtils.createLookup(manager, getActionMap())); - } - - private void initToolbar() { - Toolbar toolbar = new Toolbar(); - this.add(toolbar, BorderLayout.NORTH); - for (Action a : LookupUtils.lookupActions(GLOBAL_ACTIONS_FOLDER, getLookup())) { - toolbar.add(a); - } - toolbar.add(GarbageCollectAction.get(GarbageCollectAction.class).getToolbarPresenter()); - toolbar.add(new ServerPanel(getDocument())); - } - - @Override - public ExplorerManager getExplorerManager() { - return manager; - } - - public GraphDocument getDocument() { - return document; - } - - public static OutlineTopComponent findInstance() { - return (OutlineTopComponent) WindowManager.getDefault().findTopComponent(PREFERRED_ID); - } - - @Override - public int getPersistenceType() { - return TopComponent.PERSISTENCE_NEVER; - } - - @Override - protected String preferredID() { - return PREFERRED_ID; - } - - /** - * This method is called from within the constructor to initialize the form. - * WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - // //GEN-BEGIN:initComponents - private void initComponents() { - - treeView = new BeanTreeView(); - - setLayout(new java.awt.BorderLayout()); - add(treeView, java.awt.BorderLayout.CENTER); - }// //GEN-END:initComponents - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JScrollPane treeView; - // End of variables declaration//GEN-END:variables -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/actions/ImportAction.java --- a/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/actions/ImportAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.outline.actions; - -import com.oracle.graal.visualizer.outline.OutlineTopComponent; -import com.sun.hotspot.igv.data.GraphDocument; -import com.sun.hotspot.igv.data.serialization.Parser; -import com.sun.hotspot.igv.data.serialization.XMLParser; -import com.sun.hotspot.igv.settings.Settings; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import javax.swing.JFileChooser; -import javax.swing.SwingUtilities; -import javax.swing.filechooser.FileFilter; -import org.netbeans.api.progress.ProgressHandle; -import org.netbeans.api.progress.ProgressHandleFactory; -import org.openide.DialogDisplayer; -import org.openide.NotifyDescriptor; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.awt.ActionReferences; -import org.openide.awt.ActionRegistration; -import org.openide.util.RequestProcessor; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -@ActionID(id = "com.oracle.graal.visualizer.outline.actions.ImportAction", category = "File") -@ActionRegistration(displayName = "Import", iconBase="com/oracle/graal/visualizer/outline/images/import.png") -@ActionReferences(value = { - @ActionReference(path = "Menu/File", position = 100), - @ActionReference(path = OutlineTopComponent.GLOBAL_ACTIONS_FOLDER)}) -public final class ImportAction implements ActionListener { - - public static FileFilter getFileFilter() { - return new FileFilter() { - - @Override - public boolean accept(File f) { - return f.getName().toLowerCase().endsWith(".xml") || f.isDirectory(); - } - - @Override - public String getDescription() { - return "XML files (*.xml)"; - } - }; - } - - @Override - public void actionPerformed(ActionEvent e) { - - JFileChooser fc = new JFileChooser(); - fc.setFileFilter(ImportAction.getFileFilter()); - fc.setCurrentDirectory(new File(Settings.get().get(Settings.DIRECTORY, Settings.DIRECTORY_DEFAULT))); - - if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { - File file = fc.getSelectedFile(); - - File dir = file; - if (!dir.isDirectory()) { - dir = dir.getParentFile(); - } - - Settings.get().put(Settings.DIRECTORY, dir.getAbsolutePath()); - - try { - final FileInputStream inputStream = new FileInputStream(file); - final InputSource is = new InputSource(inputStream); - - final ProgressHandle handle = ProgressHandleFactory.createHandle("Opening file " + file.getName()); - final int basis = 1000; - handle.start(basis); - final int start = inputStream.available(); - - final XMLParser.ParseMonitor parseMonitor = new XMLParser.ParseMonitor() { - - @Override - public void setProgress(double d) { - try { - int curAvailable = inputStream.available(); - int prog = (int) (basis * (double) (start - curAvailable) / (double) start); - handle.progress(prog); - } catch (IOException ex) { - } - } - - @Override - public void setState(String state) { - setProgress(0.0); - handle.progress(state); - } - }; - final Parser parser = new Parser(); - final OutlineTopComponent component = OutlineTopComponent.findInstance(); - - component.requestActive(); - - RequestProcessor.getDefault().post(new Runnable() { - - @Override - public void run() { - try { - final GraphDocument document = parser.parse(is, parseMonitor); - parseMonitor.setState("Finishing"); - SwingUtilities.invokeLater(new Runnable(){ - - @Override - public void run() { - component.getDocument().addGraphDocument(document); - } - }); - } catch (SAXException ex) { - String s = "Exception during parsing the XML file, could not load document!"; - if (ex instanceof XMLParser.MissingAttributeException) { - XMLParser.MissingAttributeException e = (XMLParser.MissingAttributeException) ex; - s += "\nMissing attribute \"" + e.getAttributeName() + "\""; - } - NotifyDescriptor d = new NotifyDescriptor.Message(s, NotifyDescriptor.ERROR_MESSAGE); - DialogDisplayer.getDefault().notify(d); - } - handle.finish(); - } - }); - - } catch (IOException ex) { - DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message("Error reading file!", NotifyDescriptor.ERROR_MESSAGE)); - } - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/actions/RemoveAction.java --- a/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/actions/RemoveAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.oracle.graal.visualizer.outline.actions; - -import com.oracle.graal.visualizer.outline.OutlineTopComponent; -import com.sun.hotspot.igv.data.FolderElement; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.List; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.awt.ActionReferences; -import org.openide.awt.ActionRegistration; - -@ActionID(id = "com.oracle.graal.visualizer.outline.actions.RemoveAction", category = "Edit") -@ActionRegistration(displayName = "Remove", iconBase = "com/oracle/graal/visualizer/outline/images/remove.png") -@ActionReferences(value = { - @ActionReference(path = "Menu/File", position = 400), - @ActionReference(path = OutlineTopComponent.NODE_ACTIONS_FOLDER)}) -public final class RemoveAction implements ActionListener { - - List elements; - - public RemoveAction(List elements) { - this.elements = elements; - } - - @Override - public void actionPerformed(ActionEvent e) { - for (FolderElement element : elements) { - element.getParent().removeElement(element); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/actions/RemoveAllAction.java --- a/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/actions/RemoveAllAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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 com.oracle.graal.visualizer.outline.actions; - -import com.oracle.graal.visualizer.outline.OutlineTopComponent; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.awt.ActionReferences; -import org.openide.awt.ActionRegistration; - -@ActionID(id = "com.oracle.graal.visualizer.outline.actions.RemoveAllAction", category = "Edit") -@ActionRegistration(displayName = "Remove all", iconBase = "com/oracle/graal/visualizer/outline/images/removeall.png") -@ActionReferences(value = { - @ActionReference(path = "Menu/File", position = 500), - @ActionReference(path = OutlineTopComponent.GLOBAL_ACTIONS_FOLDER)}) -public final class RemoveAllAction implements ActionListener { - - @Override - public void actionPerformed(ActionEvent e) { - OutlineTopComponent.findInstance().getDocument().clear(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/actions/SaveAllAction.java --- a/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/actions/SaveAllAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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 com.oracle.graal.visualizer.outline.actions; - -import com.oracle.graal.visualizer.outline.OutlineTopComponent; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.awt.ActionReferences; -import org.openide.awt.ActionRegistration; - -@ActionID(id = "com.oracle.graal.visualizer.outline.actions.SaveAllAction", category = "File") -@ActionRegistration(displayName = "Save all..", iconBase = "com/oracle/graal/visualizer/outline/images/saveall.gif") -@ActionReferences(value = { - @ActionReference(path = "Menu/File", position = 300), - @ActionReference(path = OutlineTopComponent.GLOBAL_ACTIONS_FOLDER)}) -public final class SaveAllAction implements ActionListener { - - @Override - public void actionPerformed(ActionEvent e) { - final OutlineTopComponent component = OutlineTopComponent.findInstance(); - SaveAsAction.save(component.getDocument()); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/actions/SaveAsAction.java --- a/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/actions/SaveAsAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.outline.actions; - -import com.oracle.graal.visualizer.outline.OutlineTopComponent; -import com.sun.hotspot.igv.data.Folder; -import com.sun.hotspot.igv.data.FolderElement; -import com.sun.hotspot.igv.data.GraphDocument; -import com.sun.hotspot.igv.data.serialization.Printer; -import com.sun.hotspot.igv.settings.Settings; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.*; -import java.util.List; -import javax.swing.JFileChooser; -import javax.swing.JOptionPane; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.awt.ActionReferences; -import org.openide.awt.ActionRegistration; - -@ActionID(id = "com.oracle.graal.visualizer.outline.actions.SaveAsAction", category = "File") -@ActionRegistration(displayName = "Save as...", iconBase="com/oracle/graal/visualizer/outline/images/save.png") -@ActionReferences(value = { - @ActionReference(path = "Menu/File", position = 200), - @ActionReference(path = OutlineTopComponent.NODE_ACTIONS_FOLDER)}) -public final class SaveAsAction implements ActionListener { - - private final List elements; - - public SaveAsAction(List elements) { - this.elements = elements; - } - - - @Override - public void actionPerformed(ActionEvent e) { - GraphDocument doc = new GraphDocument(); - outer: for (FolderElement element : elements) { - Folder cur = element.getParent(); - while (cur instanceof FolderElement) { - FolderElement curElement = (FolderElement) cur; - if (elements.contains(curElement)) { - continue outer; - } - cur = curElement.getParent(); - } - - Folder previousParent = element.getParent(); - doc.addElement(element); - element.setParent(previousParent); - } - - save(doc); - } - - public static void save(GraphDocument doc) { - JFileChooser fc = new JFileChooser(); - fc.setFileFilter(ImportAction.getFileFilter()); - fc.setCurrentDirectory(new File(Settings.get().get(Settings.DIRECTORY, Settings.DIRECTORY_DEFAULT))); - - if (fc.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) { - File file = fc.getSelectedFile(); - if (!file.getName().contains(".")) { - file = new File(file.getAbsolutePath() + ".xml"); - } - - File dir = file; - if (!dir.isDirectory()) { - dir = dir.getParentFile(); - } - Settings.get().put(Settings.DIRECTORY, dir.getAbsolutePath()); - try { - try (Writer writer = new OutputStreamWriter(new FileOutputStream(file))) { - Printer p = new Printer(); - p.export(writer, doc); - } - } catch (IOException e) { - JOptionPane.showMessageDialog(null, "Error writing file " + file.getAbsolutePath()); - } - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/import.png Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/import.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/leaf_node.gif Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/leaf_node.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/node.gif Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/node.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/remove.png Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/remove.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/removeall.png Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/removeall.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/save.png Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/save.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/saveall.gif Binary file visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/images/saveall.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/layer.xml --- a/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/layer.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/server/Bundle.properties --- a/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/server/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -OpenIDE-Module-Name=NetworkConnection diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/server/Client.java --- a/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/server/Client.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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 com.oracle.graal.visualizer.outline.server; - -import com.sun.hotspot.igv.data.serialization.Parser; -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.Socket; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -public class Client implements Runnable { - - private Socket socket; - private ServerCallback callback; - - public Client(Socket socket, ServerCallback callback) { - this.callback = callback; - this.socket = socket; - } - - @Override - public void run() { - callback.connectionOpened(socket.getInetAddress()); - try { - InputStream inputStream = new BufferedInputStream(socket.getInputStream()); - InputSource is = new InputSource(inputStream); - - try { - Parser parser = new Parser(callback); - parser.parse(is, null); - } catch (SAXException ex) { - throw new IOException(ex); - } - } catch (IOException ex) { - } finally { - try { - socket.close(); - } catch (IOException ex) { - } - callback.connectionClosed(); - } - } -} \ No newline at end of file diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/server/Server.java --- a/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/server/Server.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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 com.oracle.graal.visualizer.outline.server; - -import java.io.IOException; -import java.net.ServerSocket; -import java.net.Socket; -import org.openide.DialogDisplayer; -import org.openide.NotifyDescriptor; -import org.openide.util.RequestProcessor; - -public class Server { - - private Runnable serverRunnable; - private ServerSocket serverSocket; - - private Server() {} - - - public static Server start(final ServerCallback callback, int port) { - - final Server server = new Server(); - - try { - server.serverSocket = new java.net.ServerSocket(port); - } catch (IOException ex) { - NotifyDescriptor message = new NotifyDescriptor.Message("Could not create server. Listening for incoming data is disabled.", NotifyDescriptor.ERROR_MESSAGE); - DialogDisplayer.getDefault().notifyLater(message); - return null; - } - - Runnable runnable = new Runnable() { - - @Override - public void run() { - while (true) { - try { - Socket clientSocket = server.serverSocket.accept(); - if (server.serverRunnable != this) { - clientSocket.close(); - return; - } - RequestProcessor.getDefault().post(new Client(clientSocket, callback), 0, Thread.MAX_PRIORITY); - } catch (IOException ex) { - server.serverSocket = null; - NotifyDescriptor message = new NotifyDescriptor.Message("Error during listening for incoming connections. Listening for incoming data is disabled.", NotifyDescriptor.ERROR_MESSAGE); - DialogDisplayer.getDefault().notifyLater(message); - return; - } - } - } - }; - - server.serverRunnable = runnable; - RequestProcessor.getDefault().post(runnable, 0, Thread.MAX_PRIORITY); - return server; - } - - void shutdown() { - try { - serverSocket.close(); - } catch (IOException ex) { - } - - serverSocket = null; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/server/ServerCallback.java --- a/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/server/ServerCallback.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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 com.oracle.graal.visualizer.outline.server; - -import com.sun.hotspot.igv.data.services.GroupCallback; -import java.net.InetAddress; - -public interface ServerCallback extends GroupCallback { - - public void connectionOpened(InetAddress inetAddress); - - public void connectionClosed(); - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/server/ServerPanel.java --- a/visualizer/OutlineView/src/com/oracle/graal/visualizer/outline/server/ServerPanel.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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 com.oracle.graal.visualizer.outline.server; - -import com.sun.hotspot.igv.data.GraphDocument; -import com.sun.hotspot.igv.data.Group; -import com.sun.hotspot.igv.settings.Settings; -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Font; -import java.net.InetAddress; -import java.util.prefs.PreferenceChangeEvent; -import java.util.prefs.PreferenceChangeListener; -import javax.swing.BorderFactory; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; - -public class ServerPanel extends JPanel { - - private final static int BORDER_SIZE = 2; - JLabel label; - private Server server; - private int port = -1; - private int numberOfConnections; - private final GraphDocument document; - private final PreferenceChangeListener preferenceChanged = new PreferenceChangeListener() { - - @Override - public void preferenceChange(PreferenceChangeEvent evt) { - updateServer(); - } - }; - private ServerCallback callback = new ServerCallback() { - - @Override - public void connectionOpened(InetAddress inetAddress) { - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - numberOfConnections++; - updateLabel(); - } - }); - } - - @Override - public void connectionClosed() { - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - numberOfConnections--; - updateLabel(); - } - }); - } - - @Override - public void started(Group g) { - document.addElement(g); - } - }; - - private void updateLabel() { - if (numberOfConnections == 0) { - label.setText(String.format("Listening on %d", port)); - label.setFont(label.getFont().deriveFont(Font.PLAIN)); - } else { - label.setText(String.format("%d connections", numberOfConnections)); - label.setFont(label.getFont().deriveFont(Font.BOLD)); - } - } - - private void updateServer() { - int curPort = Integer.parseInt(Settings.get().get(Settings.PORT, Settings.PORT_DEFAULT)); - if (curPort != port) { - port = curPort; - if (server != null) { - server.shutdown(); - } - server = Server.start(callback, port); - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { - updateLabel(); - } - }); - } - } - - public ServerPanel(GraphDocument document) { - - this.document = document; - Settings.get().addPreferenceChangeListener(preferenceChanged); - label = new JLabel(); - label.setBorder(BorderFactory.createEmptyBorder(0, BORDER_SIZE, 0, BORDER_SIZE)); - this.setLayout(new BorderLayout()); - this.add(label, BorderLayout.WEST); - updateServer(); - } - - public Component getToolbarPresenter() { - return label; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SelectionCoordinator/src/com/sun/hotspot/igv/selectioncoordinator/Bundle.properties --- a/visualizer/SelectionCoordinator/src/com/sun/hotspot/igv/selectioncoordinator/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -OpenIDE-Module-Name=SelectionCoordinator diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SelectionCoordinator/src/com/sun/hotspot/igv/selectioncoordinator/SelectionCoordinator.java --- a/visualizer/SelectionCoordinator/src/com/sun/hotspot/igv/selectioncoordinator/SelectionCoordinator.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.sun.hotspot.igv.selectioncoordinator; - -import com.sun.hotspot.igv.data.ChangedEvent; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -/** - * - * @author Thomas - */ -public class SelectionCoordinator { - - private static SelectionCoordinator singleInstance = new SelectionCoordinator(); - private Set selectedObjects; - private Set highlightedObjects; - private ChangedEvent selectedChangedEvent; - private ChangedEvent highlightedChangedEvent; - - public static SelectionCoordinator getInstance() { - return singleInstance; - } - - private SelectionCoordinator() { - selectedChangedEvent = new ChangedEvent<>(this); - highlightedChangedEvent = new ChangedEvent<>(this); - selectedObjects = new HashSet<>(); - highlightedObjects = new HashSet<>(); - } - - public Set getSelectedObjects() { - return Collections.unmodifiableSet(selectedObjects); - } - - public Set getHighlightedObjects() { - return Collections.unmodifiableSet(highlightedObjects); - } - - public ChangedEvent getHighlightedChangedEvent() { - return highlightedChangedEvent; - } - - public ChangedEvent getSelectedChangedEvent() { - return selectedChangedEvent; - } - - public void addHighlighted(Object o) { - if (!highlightedObjects.contains(o)) { - highlightedObjects.add(o); - highlightedObjectsChanged(); - } - } - - public void removeHighlighted(Object o) { - if (highlightedObjects.contains(o)) { - highlightedObjects.remove(o); - highlightedObjectsChanged(); - } - } - - public void addAllHighlighted(Set s) { - int oldSize = highlightedObjects.size(); - highlightedObjects.addAll(s); - if (oldSize != highlightedObjects.size()) { - highlightedObjectsChanged(); - } - } - - public void removeAllHighlighted(Set s) { - int oldSize = highlightedObjects.size(); - highlightedObjects.removeAll(s); - if (oldSize != highlightedObjects.size()) { - highlightedObjectsChanged(); - } - } - - private void highlightedObjectsChanged() { - highlightedChangedEvent.fire(); - } - - public void addAllSelected(Set s) { - int oldSize = selectedObjects.size(); - selectedObjects.addAll(s); - if (oldSize != selectedObjects.size()) { - selectedObjectsChanged(); - } - } - - public void removeAllSelected(Set s) { - int oldSize = selectedObjects.size(); - selectedObjects.removeAll(s); - if (oldSize != selectedObjects.size()) { - selectedObjectsChanged(); - } - } - - public void setSelectedObjects(Set s) { - assert s != null; - selectedObjects.clear(); - selectedObjects.addAll(s); - selectedObjectsChanged(); - } - - private void selectedObjectsChanged() { - selectedChangedEvent.fire(); - } - - public void setHighlightedObjects(Set s) { - assert s != null; - this.highlightedObjects.clear(); - this.highlightedObjects.addAll(s); - highlightedObjectsChanged(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Settings/build.xml --- a/visualizer/Settings/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project com.sun.hotspot.igv.settings. - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Settings/manifest.mf --- a/visualizer/Settings/manifest.mf Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.sun.hotspot.igv.settings -OpenIDE-Module-Layer: com/sun/hotspot/igv/settings/layer.xml -OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/settings/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Settings/nbproject/build-impl.xml --- a/visualizer/Settings/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Settings/nbproject/genfiles.properties --- a/visualizer/Settings/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -build.xml.data.CRC32=8869440a -build.xml.script.CRC32=7ef09117 -build.xml.stylesheet.CRC32=79c3b980 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=8869440a -nbproject/build-impl.xml.script.CRC32=1a0e7f21 -nbproject/build-impl.xml.stylesheet.CRC32=deb65f65 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Settings/nbproject/platform.properties --- a/visualizer/Settings/nbproject/platform.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -# Deprecated since 5.0u1; for compatibility with 5.0: -disabled.clusters=\ - apisupport1,\ - harness,\ - ide8,\ - java1,\ - nb6.0,\ - profiler2 -disabled.modules=\ - org.netbeans.core.execution,\ - org.netbeans.core.multiview,\ - org.netbeans.core.output2,\ - org.netbeans.modules.applemenu,\ - org.netbeans.modules.autoupdate.services,\ - org.netbeans.modules.autoupdate.ui,\ - org.netbeans.modules.core.kit,\ - org.netbeans.modules.favorites,\ - org.netbeans.modules.javahelp,\ - org.netbeans.modules.masterfs,\ - org.netbeans.modules.options.keymap,\ - org.netbeans.modules.sendopts,\ - org.netbeans.modules.templates,\ - org.openide.compat,\ - org.openide.execution,\ - org.openide.util.enumerations -enabled.clusters=\ - platform7 -nbjdk.active=JDK_1.6 -nbplatform.active=default diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Settings/nbproject/project.properties --- a/visualizer/Settings/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -javac.source=1.7 -javac.compilerargs=-Xlint -Xlint:-serial diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Settings/nbproject/project.xml --- a/visualizer/Settings/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - com.sun.hotspot.igv.settings - - - - org.jdesktop.layout - - - - 1 - 1.16.1 - - - - org.netbeans.modules.options.api - - - - 1 - 1.21.1 - - - - org.openide.awt - - - - 7.30.1 - - - - org.openide.util - - - - 8.14.1 - - - - org.openide.util.lookup - - - - 8.6.1 - - - - - com.sun.hotspot.igv.settings - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Settings/nbproject/suite.properties --- a/visualizer/Settings/nbproject/suite.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -suite.dir=${basedir}/.. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Settings/src/com/sun/hotspot/igv/settings/Bundle.properties --- a/visualizer/Settings/src/com/sun/hotspot/igv/settings/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -AdvancedOption_DisplayName_Settings=Settings -AdvancedOption_Tooltip_Settings=Application Settings -OpenIDE-Module-Name=Settings -OptionsCategory_Name_View=General -OptionsCategory_Title_View=View Settings diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Settings/src/com/sun/hotspot/igv/settings/Settings.java --- a/visualizer/Settings/src/com/sun/hotspot/igv/settings/Settings.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/* - * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 com.sun.hotspot.igv.settings; - -import java.util.prefs.Preferences; - -/** - * - * @author Thomas Wuerthinger - */ -public class Settings { - - public final static String NODE_TEXT = "nodeText"; - public final static String NODE_TEXT_DEFAULT = "[idx] [name]"; - public final static String NODE_WIDTH = "nodeWidth"; - public final static String NODE_WIDTH_DEFAULT = "100"; - public final static String PORT = "port"; - public final static String PORT_DEFAULT = "4444"; - public final static String DIRECTORY = "directory"; - public final static String DIRECTORY_DEFAULT = System.getProperty("user.dir"); - - public static Preferences get() { - return Preferences.userNodeForPackage(Settings.class); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Settings/src/com/sun/hotspot/igv/settings/ViewOptionsCategory.java --- a/visualizer/Settings/src/com/sun/hotspot/igv/settings/ViewOptionsCategory.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.settings; - -import javax.swing.Icon; -import javax.swing.ImageIcon; -import org.netbeans.spi.options.OptionsCategory; -import org.netbeans.spi.options.OptionsPanelController; -import org.openide.util.ImageUtilities; -import org.openide.util.NbBundle; - -/** - * - * @author Thomas Wuerthinger - */ -public final class ViewOptionsCategory extends OptionsCategory { - - @Override - public Icon getIcon() { - return new ImageIcon(ImageUtilities.loadImage("com/sun/hotspot/igv/settings/settings.png")); - } - - @Override - public String getCategoryName() { - return NbBundle.getMessage(ViewOptionsCategory.class, "OptionsCategory_Name_View"); - } - - @Override - public String getTitle() { - return NbBundle.getMessage(ViewOptionsCategory.class, "OptionsCategory_Title_View"); - } - - @Override - public OptionsPanelController create() { - return new ViewOptionsPanelController(); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Settings/src/com/sun/hotspot/igv/settings/ViewOptionsPanelController.java --- a/visualizer/Settings/src/com/sun/hotspot/igv/settings/ViewOptionsPanelController.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.settings; - -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import javax.swing.JComponent; -import org.netbeans.spi.options.OptionsPanelController; -import org.openide.util.HelpCtx; -import org.openide.util.Lookup; - -/** - * - * @author Thomas Wuerthinger - */ -final class ViewOptionsPanelController extends OptionsPanelController { - - private ViewPanel panel; - private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); - private boolean changed; - - @Override - public void update() { - getPanel().load(); - changed = false; - } - - @Override - public void applyChanges() { - getPanel().store(); - changed = false; - } - - @Override - public void cancel() { - // need not do anything special, if no changes have been persisted yet - } - - @Override - public boolean isValid() { - return getPanel().valid(); - } - - @Override - public boolean isChanged() { - return changed; - } - - @Override - public HelpCtx getHelpCtx() { - return null; // new HelpCtx("...ID") if you have a help set - } - - @Override - public JComponent getComponent(Lookup masterLookup) { - return getPanel(); - } - - @Override - public void addPropertyChangeListener(PropertyChangeListener l) { - pcs.addPropertyChangeListener(l); - } - - @Override - public void removePropertyChangeListener(PropertyChangeListener l) { - pcs.removePropertyChangeListener(l); - } - - private ViewPanel getPanel() { - if (panel == null) { - panel = new ViewPanel(this); - } - return panel; - } - - void changed() { - if (!changed) { - changed = true; - pcs.firePropertyChange(OptionsPanelController.PROP_CHANGED, false, true); - } - pcs.firePropertyChange(OptionsPanelController.PROP_VALID, null, null); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Settings/src/com/sun/hotspot/igv/settings/ViewPanel.form --- a/visualizer/Settings/src/com/sun/hotspot/igv/settings/ViewPanel.form Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,121 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Settings/src/com/sun/hotspot/igv/settings/ViewPanel.java --- a/visualizer/Settings/src/com/sun/hotspot/igv/settings/ViewPanel.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.settings; - -/** - * - * @author Thomas Wuerthinger - */ -final class ViewPanel extends javax.swing.JPanel { - - private final ViewOptionsPanelController controller; - - ViewPanel(ViewOptionsPanelController controller) { - this.controller = controller; - initComponents(); - } - - /** This method is called from within the constructor to - * initialize the form. - * WARNING: Do NOT modify this code. The content of this method is - * always regenerated by the Form Editor. - */ - // //GEN-BEGIN:initComponents - private void initComponents() { - - jPanel1 = new javax.swing.JPanel(); - jLabel1 = new javax.swing.JLabel(); - jLabel2 = new javax.swing.JLabel(); - portSpinner = new javax.swing.JSpinner(); - jScrollPane1 = new javax.swing.JScrollPane(); - nodeTextArea = new javax.swing.JTextArea(); - nodeWidthSpinner = new javax.swing.JSpinner(); - jLabel3 = new javax.swing.JLabel(); - - org.openide.awt.Mnemonics.setLocalizedText(jLabel1, "Node Text"); - - org.openide.awt.Mnemonics.setLocalizedText(jLabel2, "Node Width"); - - nodeTextArea.setColumns(20); - nodeTextArea.setRows(5); - jScrollPane1.setViewportView(nodeTextArea); - - org.openide.awt.Mnemonics.setLocalizedText(jLabel3, "Network Port"); - - org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1); - jPanel1.setLayout(jPanel1Layout); - jPanel1Layout.setHorizontalGroup( - jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel1Layout.createSequentialGroup() - .addContainerGap() - .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(jLabel1) - .add(jLabel3) - .add(jLabel2)) - .add(39, 39, 39) - .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(portSpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 63, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) - .add(nodeWidthSpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 63, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) - .add(jScrollPane1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 365, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)) - .addContainerGap()) - ); - jPanel1Layout.setVerticalGroup( - jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(jPanel1Layout.createSequentialGroup() - .addContainerGap() - .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(jPanel1Layout.createSequentialGroup() - .add(jScrollPane1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) - .add(18, 18, 18) - .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) - .add(nodeWidthSpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) - .add(jLabel2)) - .add(18, 18, 18) - .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) - .add(portSpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) - .add(jLabel3))) - .add(jLabel1)) - .add(73, 73, 73)) - ); - - org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(layout.createSequentialGroup() - .addContainerGap() - .add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addContainerGap()) - ); - layout.setVerticalGroup( - layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) - .add(layout.createSequentialGroup() - .addContainerGap() - .add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 232, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) - .addContainerGap(206, Short.MAX_VALUE)) - ); - }// //GEN-END:initComponents - void load() { - nodeTextArea.setText(Settings.get().get(Settings.NODE_TEXT, Settings.NODE_TEXT_DEFAULT)); - nodeWidthSpinner.setValue(Integer.parseInt(Settings.get().get(Settings.NODE_WIDTH, Settings.NODE_WIDTH_DEFAULT))); - portSpinner.setValue(Integer.parseInt(Settings.get().get(Settings.PORT, Settings.PORT_DEFAULT))); - } - - void store() { - Settings.get().put(Settings.NODE_TEXT, nodeTextArea.getText()); - Settings.get().put(Settings.NODE_WIDTH, nodeWidthSpinner.getValue().toString()); - Settings.get().put(Settings.PORT, portSpinner.getValue().toString()); - } - - boolean valid() { - return true; - } - // Variables declaration - do not modify//GEN-BEGIN:variables - private javax.swing.JLabel jLabel1; - private javax.swing.JLabel jLabel2; - private javax.swing.JLabel jLabel3; - private javax.swing.JPanel jPanel1; - private javax.swing.JScrollPane jScrollPane1; - private javax.swing.JTextArea nodeTextArea; - private javax.swing.JSpinner nodeWidthSpinner; - private javax.swing.JSpinner portSpinner; - // End of variables declaration//GEN-END:variables -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Settings/src/com/sun/hotspot/igv/settings/layer.xml --- a/visualizer/Settings/src/com/sun/hotspot/igv/settings/layer.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Settings/src/com/sun/hotspot/igv/settings/settings.png Binary file visualizer/Settings/src/com/sun/hotspot/igv/settings/settings.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SharedActions/build.xml --- a/visualizer/SharedActions/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project com.oracle.graal.visualizer.sharedactions. - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SharedActions/manifest.mf --- a/visualizer/SharedActions/manifest.mf Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.oracle.graal.visualizer.sharedactions -OpenIDE-Module-Localizing-Bundle: com/oracle/graal/visualizer/sharedactions/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SharedActions/nbproject/build-impl.xml --- a/visualizer/SharedActions/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ - - - - - - - - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SharedActions/nbproject/genfiles.properties --- a/visualizer/SharedActions/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -build.xml.data.CRC32=c3bdef4e -build.xml.script.CRC32=da3659b1 -build.xml.stylesheet.CRC32=a56c6a5b@2.47.1 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=c3bdef4e -nbproject/build-impl.xml.script.CRC32=567ad23a -nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SharedActions/nbproject/project.properties --- a/visualizer/SharedActions/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -javac.source=1.7 -javac.compilerargs=-Xlint -Xlint:-serial diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SharedActions/nbproject/project.xml --- a/visualizer/SharedActions/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - com.oracle.graal.visualizer.sharedactions - - - - com.sun.hotspot.igv.svg - - - - 1.0 - - - - org.openide.actions - - - - 6.24.1 - - - - org.openide.awt - - - - 7.39.1 - - - - org.openide.dialogs - - - - 7.23.1 - - - - org.openide.util - - - - 8.19.1 - - - - - com.oracle.graal.visualizer.sharedactions - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SharedActions/nbproject/suite.properties --- a/visualizer/SharedActions/nbproject/suite.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -suite.dir=${basedir}/.. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/Bundle.properties --- a/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -OpenIDE-Module-Name=SharedActions diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ExportSVGAction.java --- a/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ExportSVGAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.oracle.graal.visualizer.sharedactions; - -import com.sun.hotspot.igv.svg.BatikSVG; -import java.awt.Graphics2D; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.*; -import javax.swing.JFileChooser; -import org.openide.DialogDisplayer; -import org.openide.NotifyDescriptor; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.awt.ActionRegistration; -import org.openide.util.NbPreferences; - -@ActionID(id = "com.oracle.graal.visualizer.sharedactions.ExportSVGAction", category = "File") -@ActionRegistration(displayName = "Export", iconBase = "com/oracle/graal/visualizer/sharedactions/images/export.png") -@ActionReference(path = "Menu/File", position = 600) -public class ExportSVGAction implements ActionListener { - - private static final String PREFERENCE_DIR = "dir"; - private ExportSVGCookie exportCookie; - - public ExportSVGAction(ExportSVGCookie exportCookie) { - this.exportCookie = exportCookie; - } - - @Override - public void actionPerformed(ActionEvent actionEvent) { - Graphics2D svgGenerator = BatikSVG.createGraphicsObject(); - if (svgGenerator == null) { - NotifyDescriptor message = new NotifyDescriptor.Message("For export to SVG files the Batik SVG Toolkit must be intalled.", NotifyDescriptor.ERROR_MESSAGE); - DialogDisplayer.getDefault().notifyLater(message); - return; - } - - File f = selectFile(); - if (f != null) { - exportCookie.paint(svgGenerator); - FileOutputStream os = null; - try { - os = new FileOutputStream(f); - Writer out = new OutputStreamWriter(os, "UTF-8"); - BatikSVG.printToStream(svgGenerator, out, true); - } catch (FileNotFoundException e) { - NotifyDescriptor message = new NotifyDescriptor.Message("For export to SVG files the Batik SVG Toolkit must be intalled.", NotifyDescriptor.ERROR_MESSAGE); - DialogDisplayer.getDefault().notifyLater(message); - - } catch (UnsupportedEncodingException e) { - } finally { - if (os != null) { - try { - os.close(); - } catch (IOException e) { - } - } - } - } - } - - private File selectFile() { - JFileChooser fc = new JFileChooser(); - fc.setFileFilter(new javax.swing.filechooser.FileFilter() { - - @Override - public boolean accept(File f) { - return true; - } - - @Override - public String getDescription() { - return "SVG files (*.svg)"; - } - }); - fc.setCurrentDirectory(new File(NbPreferences.forModule(ExportSVGAction.class).get(PREFERENCE_DIR, "~"))); - - - if (fc.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) { - File file = fc.getSelectedFile(); - if (!file.getName().contains(".")) { - file = new File(file.getAbsolutePath() + ".svg"); - } - - File dir = file; - if (!dir.isDirectory()) { - dir = dir.getParentFile(); - } - - NbPreferences.forModule(ExportSVGAction.class).put(PREFERENCE_DIR, dir.getAbsolutePath()); - return file; - } - - return null; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ExportSVGCookie.java --- a/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ExportSVGCookie.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.oracle.graal.visualizer.sharedactions; - -import java.awt.Graphics2D; - -public interface ExportSVGCookie { - void paint(Graphics2D g); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ShowAllAction.java --- a/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ShowAllAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.oracle.graal.visualizer.sharedactions; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.List; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.awt.ActionRegistration; - -@ActionID(id = "com.oracle.graal.visualizer.sharedactions.ShowAllAction", category = "View") -@ActionRegistration(displayName = "Fit Scene to Window", iconBase="com/oracle/graal/visualizer/sharedactions/images/autosize.gif") -@ActionReference(path = "Menu/View", position = 500) -public class ShowAllAction implements ActionListener { - - private List zoomCookies; - - public ShowAllAction(List zoomCookies) { - this.zoomCookies = zoomCookies; - } - - @Override - public void actionPerformed(ActionEvent e) { - for (ZoomCookie c : zoomCookies) { - c.showAll(); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ZoomCookie.java --- a/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ZoomCookie.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.oracle.graal.visualizer.sharedactions; - -public interface ZoomCookie { - void zoomIn(); - void zoomOut(); - void showAll(); - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ZoomInAction.java --- a/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ZoomInAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.oracle.graal.visualizer.sharedactions; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.List; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.awt.ActionRegistration; - -@ActionID(id = "com.oracle.graal.visualizer.sharedactions.ZoomInAction", category = "View") -@ActionRegistration(displayName = "Zoom In", iconBase="com/oracle/graal/visualizer/sharedactions/images/zoomin.gif") -@ActionReference(path = "Menu/View", position = 600) -public class ZoomInAction implements ActionListener { - - private List zoomCookies; - - public ZoomInAction(List zoomCookies) { - this.zoomCookies = zoomCookies; - } - - @Override - public void actionPerformed(ActionEvent e) { - for (ZoomCookie c : zoomCookies) { - c.zoomIn(); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ZoomOutAction.java --- a/visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/ZoomOutAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.oracle.graal.visualizer.sharedactions; - -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.List; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.awt.ActionRegistration; - -@ActionID(id = "com.oracle.graal.visualizer.sharedactions.ZoomOutAction", category = "View") -@ActionRegistration(displayName = "Zoom Out", iconBase="com/oracle/graal/visualizer/sharedactions/images/zoomout.gif") -@ActionReference(path = "Menu/View", position = 700) -public class ZoomOutAction implements ActionListener { - - private List zoomCookies; - - public ZoomOutAction(List zoomCookies) { - this.zoomCookies = zoomCookies; - } - - @Override - public void actionPerformed(ActionEvent e) { - for (ZoomCookie c : zoomCookies) { - c.zoomOut(); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/images/autosize.gif Binary file visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/images/autosize.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/images/export.png Binary file visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/images/export.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/images/zoomin.gif Binary file visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/images/zoomin.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/images/zoomout.gif Binary file visualizer/SharedActions/src/com/oracle/graal/visualizer/sharedactions/images/zoomout.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SnapshotsView/build.xml --- a/visualizer/SnapshotsView/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project com.oracle.graal.visualizer.snapshots. - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SnapshotsView/manifest.mf --- a/visualizer/SnapshotsView/manifest.mf Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.oracle.graal.visualizer.snapshots -OpenIDE-Module-Layer: com/oracle/graal/visualizer/snapshots/layer.xml -OpenIDE-Module-Localizing-Bundle: com/oracle/graal/visualizer/snapshots/Bundle.properties -OpenIDE-Module-Requires: org.openide.windows.WindowManager -OpenIDE-Module-Specification-Version: 1.0 - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SnapshotsView/nbproject/build-impl.xml --- a/visualizer/SnapshotsView/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ - - - - - - - - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SnapshotsView/nbproject/genfiles.properties --- a/visualizer/SnapshotsView/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -build.xml.data.CRC32=8a85c130 -build.xml.script.CRC32=d28dc95d -build.xml.stylesheet.CRC32=a56c6a5b@2.47.1 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=8a85c130 -nbproject/build-impl.xml.script.CRC32=dfcb8f66 -nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.1 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SnapshotsView/nbproject/platform.properties --- a/visualizer/SnapshotsView/nbproject/platform.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,204 +0,0 @@ -cluster.path=\ - ${nbplatform.active.dir}/ide:\ - ${nbplatform.active.dir}/platform -disabled.modules=\ - com.jcraft.jsch,\ - com.jcraft.jzlib,\ - org.apache.commons.codec,\ - org.apache.commons.httpclient,\ - org.apache.commons.io,\ - org.apache.commons.lang,\ - org.apache.commons.logging,\ - org.apache.ws.commons.util,\ - org.apache.xml.resolver,\ - org.apache.xmlrpc,\ - org.eclipse.core.contenttype,\ - org.eclipse.core.jobs,\ - org.eclipse.core.net,\ - org.eclipse.core.runtime,\ - org.eclipse.core.runtime.compatibility.auth,\ - org.eclipse.equinox.app,\ - org.eclipse.equinox.common,\ - org.eclipse.equinox.preferences,\ - org.eclipse.equinox.registry,\ - org.eclipse.equinox.security,\ - org.eclipse.jgit,\ - org.eclipse.mylyn.bugzilla.core,\ - org.eclipse.mylyn.commons.core,\ - org.eclipse.mylyn.commons.net,\ - org.eclipse.mylyn.commons.xmlrpc,\ - org.eclipse.mylyn.tasks.core,\ - org.mozilla.rhino.patched,\ - org.netbeans.api.debugger,\ - org.netbeans.api.java.classpath,\ - org.netbeans.api.xml,\ - org.netbeans.core.browser,\ - org.netbeans.core.execution,\ - org.netbeans.core.ide,\ - org.netbeans.core.io.ui,\ - org.netbeans.core.multiview,\ - org.netbeans.core.nativeaccess,\ - org.netbeans.core.osgi,\ - org.netbeans.lib.cvsclient,\ - org.netbeans.lib.terminalemulator,\ - org.netbeans.libs.antlr3.runtime,\ - org.netbeans.libs.bytelist,\ - org.netbeans.libs.commons_net,\ - org.netbeans.libs.freemarker,\ - org.netbeans.libs.git,\ - org.netbeans.libs.ini4j,\ - org.netbeans.libs.jaxb,\ - org.netbeans.libs.jsr223,\ - org.netbeans.libs.junit4,\ - org.netbeans.libs.jvyamlb,\ - org.netbeans.libs.lucene,\ - org.netbeans.libs.smack,\ - org.netbeans.libs.svnClientAdapter,\ - org.netbeans.libs.svnClientAdapter.javahl,\ - org.netbeans.libs.svnClientAdapter.svnkit,\ - org.netbeans.libs.swingx,\ - org.netbeans.libs.xerces,\ - org.netbeans.modules.autoupdate.services,\ - org.netbeans.modules.autoupdate.ui,\ - org.netbeans.modules.bugtracking,\ - org.netbeans.modules.bugtracking.bridge,\ - org.netbeans.modules.bugzilla,\ - org.netbeans.modules.core.kit,\ - org.netbeans.modules.csl.api,\ - org.netbeans.modules.css.editor,\ - org.netbeans.modules.css.lib,\ - org.netbeans.modules.css.visual,\ - org.netbeans.modules.db,\ - org.netbeans.modules.db.core,\ - org.netbeans.modules.db.dataview,\ - org.netbeans.modules.db.drivers,\ - org.netbeans.modules.db.kit,\ - org.netbeans.modules.db.metadata.model,\ - org.netbeans.modules.db.mysql,\ - org.netbeans.modules.db.sql.editor,\ - org.netbeans.modules.db.sql.visualeditor,\ - org.netbeans.modules.dbapi,\ - org.netbeans.modules.defaults,\ - org.netbeans.modules.derby,\ - org.netbeans.modules.dlight.nativeexecution,\ - org.netbeans.modules.dlight.terminal,\ - org.netbeans.modules.editor.bookmarks,\ - org.netbeans.modules.editor.bracesmatching,\ - org.netbeans.modules.editor.codetemplates,\ - org.netbeans.modules.editor.completion,\ - org.netbeans.modules.editor.guards,\ - org.netbeans.modules.editor.indent.project,\ - org.netbeans.modules.editor.kit,\ - org.netbeans.modules.editor.macros,\ - org.netbeans.modules.editor.structure,\ - org.netbeans.modules.extbrowser,\ - org.netbeans.modules.extexecution,\ - org.netbeans.modules.extexecution.destroy,\ - org.netbeans.modules.favorites,\ - org.netbeans.modules.git,\ - org.netbeans.modules.glassfish.common,\ - org.netbeans.modules.gototest,\ - org.netbeans.modules.gsf.codecoverage,\ - org.netbeans.modules.gsf.testrunner,\ - org.netbeans.modules.html,\ - org.netbeans.modules.html.editor,\ - org.netbeans.modules.html.editor.lib,\ - org.netbeans.modules.html.lexer,\ - org.netbeans.modules.html.parser,\ - org.netbeans.modules.html.validation,\ - org.netbeans.modules.httpserver,\ - org.netbeans.modules.hudson,\ - org.netbeans.modules.hudson.git,\ - org.netbeans.modules.hudson.mercurial,\ - org.netbeans.modules.hudson.subversion,\ - org.netbeans.modules.hudson.tasklist,\ - org.netbeans.modules.ide.kit,\ - org.netbeans.modules.image,\ - org.netbeans.modules.javascript.editing,\ - org.netbeans.modules.javascript.hints,\ - org.netbeans.modules.javascript.kit,\ - org.netbeans.modules.javascript.refactoring,\ - org.netbeans.modules.jellytools.ide,\ - org.netbeans.modules.jumpto,\ - org.netbeans.modules.keyring.impl,\ - org.netbeans.modules.languages,\ - org.netbeans.modules.languages.diff,\ - org.netbeans.modules.languages.manifest,\ - org.netbeans.modules.languages.yaml,\ - org.netbeans.modules.lexer.nbbridge,\ - org.netbeans.modules.localhistory,\ - org.netbeans.modules.mercurial,\ - org.netbeans.modules.netbinox,\ - org.netbeans.modules.parsing.api,\ - org.netbeans.modules.parsing.lucene,\ - org.netbeans.modules.print.editor,\ - org.netbeans.modules.project.ant,\ - org.netbeans.modules.project.libraries,\ - org.netbeans.modules.projectui,\ - org.netbeans.modules.projectui.buildmenu,\ - org.netbeans.modules.projectuiapi,\ - org.netbeans.modules.properties,\ - org.netbeans.modules.properties.syntax,\ - org.netbeans.modules.refactoring.api,\ - org.netbeans.modules.schema2beans,\ - org.netbeans.modules.server,\ - org.netbeans.modules.servletapi,\ - org.netbeans.modules.spellchecker,\ - org.netbeans.modules.spellchecker.apimodule,\ - org.netbeans.modules.spellchecker.bindings.htmlxml,\ - org.netbeans.modules.spellchecker.bindings.properties,\ - org.netbeans.modules.spellchecker.dictionary_en,\ - org.netbeans.modules.spellchecker.kit,\ - org.netbeans.modules.spi.actions,\ - org.netbeans.modules.subversion,\ - org.netbeans.modules.swing.validation,\ - org.netbeans.modules.target.iterator,\ - org.netbeans.modules.tasklist.kit,\ - org.netbeans.modules.tasklist.projectint,\ - org.netbeans.modules.tasklist.todo,\ - org.netbeans.modules.tasklist.ui,\ - org.netbeans.modules.terminal,\ - org.netbeans.modules.usersguide,\ - org.netbeans.modules.utilities,\ - org.netbeans.modules.utilities.project,\ - org.netbeans.modules.versioning,\ - org.netbeans.modules.versioning.indexingbridge,\ - org.netbeans.modules.versioning.system.cvss.installer,\ - org.netbeans.modules.versioning.util,\ - org.netbeans.modules.web.client.tools.api,\ - org.netbeans.modules.web.common,\ - org.netbeans.modules.web.indent,\ - org.netbeans.modules.xml,\ - org.netbeans.modules.xml.axi,\ - org.netbeans.modules.xml.catalog,\ - org.netbeans.modules.xml.core,\ - org.netbeans.modules.xml.jaxb.api,\ - org.netbeans.modules.xml.lexer,\ - org.netbeans.modules.xml.multiview,\ - org.netbeans.modules.xml.retriever,\ - org.netbeans.modules.xml.schema.completion,\ - org.netbeans.modules.xml.schema.model,\ - org.netbeans.modules.xml.tax,\ - org.netbeans.modules.xml.text,\ - org.netbeans.modules.xml.tools,\ - org.netbeans.modules.xml.wsdl.model,\ - org.netbeans.modules.xml.xam,\ - org.netbeans.modules.xml.xdm,\ - org.netbeans.modules.xsl,\ - org.netbeans.spi.debugger.ui,\ - org.netbeans.spi.editor.hints,\ - org.netbeans.spi.navigator,\ - org.netbeans.spi.palette,\ - org.netbeans.spi.tasklist,\ - org.netbeans.spi.viewmodel,\ - org.netbeans.swing.dirchooser,\ - org.openide.compat,\ - org.openide.execution,\ - org.openide.options,\ - org.openide.util.enumerations -## Not disabled because of NetBeans bug 206347: -## Applications not using OSGi don't start on NbP 7.1 -# org.netbeans.core.netigso,\ -# org.netbeans.libs.felix,\ -# org.netbeans.libs.osgi,\ -nbplatform.active=default diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SnapshotsView/nbproject/project.properties --- a/visualizer/SnapshotsView/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -javac.source=1.6 -javac.compilerargs=-Xlint -Xlint:-serial diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SnapshotsView/nbproject/project.xml --- a/visualizer/SnapshotsView/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - com.oracle.graal.visualizer.snapshots - - - - com.oracle.graal.visualizer.editor - - - - 1.0 - - - - com.sun.hotspot.igv.data - - - - 1.0 - - - - com.sun.hotspot.igv.util - - - - 1.0 - - - - org.netbeans.modules.settings - - - - 1 - 1.33.1 - - - - org.openide.awt - - - - 7.39.1 - - - - org.openide.util - - - - 8.19.1 - - - - org.openide.util.lookup - - - - 8.11.1 - - - - org.openide.windows - - - - 6.48.1 - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SnapshotsView/nbproject/suite.properties --- a/visualizer/SnapshotsView/nbproject/suite.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -suite.dir=${basedir}/.. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/Bundle.properties --- a/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -OpenIDE-Module-Name=SnapshotsView diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/SnapshotTopComponent.form --- a/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/SnapshotTopComponent.form Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/SnapshotTopComponent.java --- a/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/SnapshotTopComponent.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.oracle.graal.visualizer.snapshots; - -import com.oracle.graal.visualizer.editor.EditorTopComponent; -import com.oracle.graal.visualizer.util.LookupUtils; -import com.sun.hotspot.igv.data.ChangedEvent; -import com.sun.hotspot.igv.data.ChangedListener; -import com.sun.hotspot.igv.util.RangeSlider; -import com.sun.hotspot.igv.util.RangeSliderModel; -import java.awt.BorderLayout; -import javax.swing.JScrollPane; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.util.Lookup.Result; -import org.openide.util.LookupEvent; -import org.openide.util.LookupListener; -import org.openide.windows.TopComponent; -import org.openide.windows.WindowManager; - -@TopComponent.Description(preferredID = SnapshotTopComponent.PREFERRED_ID, persistenceType = TopComponent.PERSISTENCE_ALWAYS) -@TopComponent.Registration(mode = "belowExplorer", openAtStartup = true) -@ActionID(category = "Window", id = "com.oracle.graal.visualizer.snapshots.SnapshotTopComponent") -@ActionReference(path = "Menu/Window") -@TopComponent.OpenActionRegistration(displayName = "Snapshot", preferredID = SnapshotTopComponent.PREFERRED_ID) -public final class SnapshotTopComponent extends TopComponent { - public static final String PREFERRED_ID = "SnapshotTopComponent"; - - private final Result result; - private final RangeSlider rangeSlider; - private final ChangedEvent rangeSliderChangedEvent = new ChangedEvent(null); - private final LookupListener lookupListener = new LookupListener() { - - @Override - public void resultChanged(LookupEvent le) { - update(); - } - }; - - private final ChangedListener rangeSliderChangedListener = new ChangedListener(){ - - @Override - public void changed(RangeSliderModel source) { - rangeSliderChangedEvent.fire(); - } - }; - - public SnapshotTopComponent() { - initComponents(); - setName("Snapshot Window"); - setToolTipText("This is a Snapshot window"); - - result = LookupUtils.getLastActiveDelegatingLookup(EditorTopComponent.class).lookupResult(RangeSliderModel.class); - result.addLookupListener(lookupListener); - this.rangeSlider = new RangeSlider(null); - this.setLayout(new BorderLayout()); - final JScrollPane scrollPane = new JScrollPane(rangeSlider); - scrollPane.getVerticalScrollBar().setUnitIncrement(RangeSlider.ITEM_HEIGHT); - this.add(scrollPane, BorderLayout.CENTER); - update(); - } - - private void update() { - RangeSliderModel newModel; - if (result.allInstances().size() > 0) { - newModel = result.allInstances().iterator().next(); - } else { - newModel = null; - } - if (rangeSlider.getModel() != null) { - rangeSlider.getModel().getChangedEvent().removeListener(rangeSliderChangedListener); - } - rangeSlider.setModel(newModel); - rangeSliderChangedEvent.changeObject(newModel); - if (newModel != null) { - newModel.getChangedEvent().addListener(rangeSliderChangedListener); - } - } - - public ChangedEvent getRangeSliderChangedEvent() { - return rangeSliderChangedEvent; - } - - public static SnapshotTopComponent findInstance() { - return (SnapshotTopComponent) WindowManager.getDefault().findTopComponent(PREFERRED_ID); - } - - /** - * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this method is always - * regenerated by the Form Editor. - */ - // //GEN-BEGIN:initComponents - private void initComponents() { - - javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); - this.setLayout(layout); - layout.setHorizontalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 400, Short.MAX_VALUE) - ); - layout.setVerticalGroup( - layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 300, Short.MAX_VALUE) - ); - }// //GEN-END:initComponents - // Variables declaration - do not modify//GEN-BEGIN:variables - // End of variables declaration//GEN-END:variables - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/actions/NextSnapshotAction.java --- a/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/actions/NextSnapshotAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.oracle.graal.visualizer.snapshots.actions; - -import com.oracle.graal.visualizer.snapshots.SnapshotTopComponent; -import com.sun.hotspot.igv.data.ChangedListener; -import com.sun.hotspot.igv.util.RangeSliderModel; -import java.awt.event.ActionEvent; -import javax.swing.AbstractAction; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.awt.ActionRegistration; - -@ActionID(id = "com.oracle.graal.visualizer.editor.actions.NextSnapshotAction", category = "View") -@ActionRegistration(displayName = "Next snapshot", iconBase = "com/oracle/graal/visualizer/snapshots/images/next_snapshot.png") -@ActionReference(path = "Menu/View", position = 150) -public final class NextSnapshotAction extends AbstractAction{ - - private RangeSliderModel model; - - public NextSnapshotAction() { - SnapshotTopComponent.findInstance().getRangeSliderChangedEvent().addListenerAndFire(changeListener); - } - private final ChangedListener changeListener = new ChangedListener() { - - @Override - public void changed(RangeSliderModel source) { - model = source; - setEnabled(model != null && model.getSecondPosition() != model.getPositions().size() - 1); - } - }; - - @Override - public void actionPerformed(ActionEvent e) { - if (model != null) { - int fp = model.getFirstPosition(); - int sp = model.getSecondPosition(); - if (sp != model.getPositions().size() - 1) { - int nfp = fp + 1; - int nsp = sp + 1; - model.setPositions(nfp, nsp); - } - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/actions/PrevSnapshotAction.java --- a/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/actions/PrevSnapshotAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.oracle.graal.visualizer.snapshots.actions; - -import com.oracle.graal.visualizer.snapshots.SnapshotTopComponent; -import com.sun.hotspot.igv.data.ChangedListener; -import com.sun.hotspot.igv.util.RangeSliderModel; -import java.awt.event.ActionEvent; -import javax.swing.AbstractAction; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.awt.ActionRegistration; - -@ActionID(id = "com.oracle.graal.visualizer.editor.actions.PrevSnapshotAction", category = "View") -@ActionRegistration(displayName = "Previous snapshot", iconBase = "com/oracle/graal/visualizer/snapshots/images/prev_snapshot.png") -@ActionReference(path = "Menu/View", position = 100) -public final class PrevSnapshotAction extends AbstractAction { - - private RangeSliderModel model; - - public PrevSnapshotAction() { - SnapshotTopComponent.findInstance().getRangeSliderChangedEvent().addListenerAndFire(changeListener); - } - private final ChangedListener changeListener = new ChangedListener() { - - @Override - public void changed(RangeSliderModel source) { - model = source; - setEnabled(model != null && model.getFirstPosition() != 0); - } - }; - - @Override - public void actionPerformed(ActionEvent e) { - if (model != null) { - int fp = model.getFirstPosition(); - int sp = model.getSecondPosition(); - if (fp != 0) { - int nfp = fp - 1; - int nsp = sp - 1; - model.setPositions(nfp, nsp); - } - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/belowExplorerWsmode.xml --- a/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/belowExplorerWsmode.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/images/next_snapshot.png Binary file visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/images/next_snapshot.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/images/prev_snapshot.png Binary file visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/images/prev_snapshot.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/layer.xml --- a/visualizer/SnapshotsView/src/com/oracle/graal/visualizer/snapshots/layer.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Util/build.xml --- a/visualizer/Util/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project com.sun.hotspot.igv.util. - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Util/manifest.mf --- a/visualizer/Util/manifest.mf Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.sun.hotspot.igv.util -OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/util/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Util/nbproject/build-impl.xml --- a/visualizer/Util/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Util/nbproject/genfiles.properties --- a/visualizer/Util/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -build.xml.data.CRC32=a470a16f -build.xml.script.CRC32=466cf03b -build.xml.stylesheet.CRC32=05353c81 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=a470a16f -nbproject/build-impl.xml.script.CRC32=39f45e01 -nbproject/build-impl.xml.stylesheet.CRC32=3f8b4615 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Util/nbproject/platform.properties --- a/visualizer/Util/nbproject/platform.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -# Deprecated since 5.0u1; for compatibility with 5.0: -disabled.clusters=\ - apisupport1,\ - harness,\ - ide8,\ - java1,\ - nb6.0,\ - profiler2 -disabled.modules=\ - org.netbeans.core.execution,\ - org.netbeans.core.multiview,\ - org.netbeans.core.output2,\ - org.netbeans.modules.applemenu,\ - org.netbeans.modules.autoupdate.services,\ - org.netbeans.modules.autoupdate.ui,\ - org.netbeans.modules.core.kit,\ - org.netbeans.modules.favorites,\ - org.netbeans.modules.javahelp,\ - org.netbeans.modules.masterfs,\ - org.netbeans.modules.options.keymap,\ - org.netbeans.modules.sendopts,\ - org.netbeans.modules.templates,\ - org.openide.compat,\ - org.openide.execution,\ - org.openide.util.enumerations -enabled.clusters=\ - platform7 -nbjdk.active=JDK_1.6 -nbplatform.active=default diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Util/nbproject/project.properties --- a/visualizer/Util/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -javac.source=1.7 -javac.compilerargs=-Xlint -Xlint:-serial diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Util/nbproject/project.xml --- a/visualizer/Util/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - com.sun.hotspot.igv.util - - - - com.sun.hotspot.igv.data - - - - 1.0 - - - - org.netbeans.api.visual - - - - 2.27.1 - - - - org.openide.nodes - - - - 7.20.1 - - - - org.openide.util - - - - 8.14.1 - - - - org.openide.util.lookup - - - - 8.6.1 - - - - org.openide.windows - - - - 6.48.1 - - - - - com.oracle.graal.visualizer.util - com.sun.hotspot.igv.util - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Util/nbproject/suite.properties --- a/visualizer/Util/nbproject/suite.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -suite.dir=${basedir}/.. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Util/src/com/oracle/graal/visualizer/util/LookupUtils.java --- a/visualizer/Util/src/com/oracle/graal/visualizer/util/LookupUtils.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.oracle.graal.visualizer.util; - -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.util.ArrayList; -import java.util.List; -import javax.swing.Action; -import org.openide.util.ContextAwareAction; -import org.openide.util.Lookup; -import org.openide.util.Lookup.Provider; -import org.openide.util.lookup.Lookups; -import org.openide.windows.TopComponent; - -/** - * Utilities that build upon the Lookup API. - */ -public class LookupUtils { - - - /** - * Creates a new lookup that will delegate to the last open window of a specified top component class. If the window is closed, the lookup will be empty. - * @param clazz the class identifying the top component type - * @return a delegating lookup - */ - public static Lookup getLastActiveDelegatingLookup(Class clazz) { - final TopComponentLookup topComponentLookupImpl = new TopComponentLookup(clazz); - TopComponent.getRegistry().addPropertyChangeListener(topComponentLookupImpl); - return topComponentLookupImpl.lookup; - } - - public static Iterable lookupActions(String path) { - return lookupActions(path, null); - } - - public static Iterable lookupActions(String path, Lookup context) { - List actions = new ArrayList<>(); - for (Action a : Lookups.forPath(path).lookupAll(Action.class)) { - Action newAction = a; - if (a instanceof ContextAwareAction && context != null) { - newAction = ((ContextAwareAction) a).createContextAwareInstance(context); - } - newAction.putValue(Action.SHORT_DESCRIPTION, newAction.getValue(Action.NAME)); - actions.add(newAction); - - } - return actions; - } - - private static class TopComponentLookup implements PropertyChangeListener { - private final Class clazz; - private final Lookup lookup; - private TopComponent lastActive; - - private final Provider lookupProvider = new Provider() { - - @Override - public Lookup getLookup() { - if (lastActive == null) { - return Lookup.EMPTY; - } else { - return lastActive.getLookup(); - } - } - }; - - public TopComponentLookup(Class clazz) { - this.clazz = clazz; - lookup = Lookups.proxy(lookupProvider); - update(); - } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - update(); - } - - private void update() { - TopComponent curActivated = TopComponent.getRegistry().getActivated(); - if (curActivated != lastActive) { - if (clazz.isAssignableFrom(curActivated.getClass())) { - // We have a new top component for our lookup. - lastActive = curActivated; - refreshLookup(); - } else { - // We have no new top component. Check if the old one is still opened. - if (lastActive != null && !TopComponent.getRegistry().getOpened().contains(lastActive)) { - // The top component was closed => Remove lookup. - lastActive = null; - refreshLookup(); - } - } - } - } - - private void refreshLookup() { - lookup.lookup(Object.class); - } - }; -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Util/src/com/sun/hotspot/igv/util/BoundedZoomAction.java --- a/visualizer/Util/src/com/sun/hotspot/igv/util/BoundedZoomAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.util; - -import java.awt.Container; -import java.awt.Dimension; -import java.awt.Point; -import java.awt.Rectangle; -import javax.swing.JComponent; -import javax.swing.JScrollPane; -import org.netbeans.api.visual.action.WidgetAction; -import org.netbeans.api.visual.action.WidgetAction.State; -import org.netbeans.api.visual.action.WidgetAction.WidgetMouseWheelEvent; -import org.netbeans.api.visual.animator.SceneAnimator; -import org.netbeans.api.visual.widget.Scene; -import org.netbeans.api.visual.widget.Widget; - -/** - * - * @author Thomas Wuerthinger - */ -public class BoundedZoomAction extends WidgetAction.Adapter { - - private double minFactor = 0.0; - private double maxFactor = Double.MAX_VALUE; - private double zoomMultiplier; - private boolean useAnimator; - - public BoundedZoomAction(double zoomMultiplier, boolean useAnimator) { - this.zoomMultiplier = zoomMultiplier; - this.useAnimator = useAnimator; - } - - public double getMinFactor() { - return minFactor; - } - - public void setMinFactor(double d) { - minFactor = d; - } - - public double getMaxFactor() { - return maxFactor; - } - - public void setMaxFactor(double d) { - maxFactor = d; - } - - private JScrollPane findScrollPane(JComponent component) { - for (;;) { - if (component == null) { - return null; - } - if (component instanceof JScrollPane) { - return ((JScrollPane) component); - } - Container parent = component.getParent(); - if (!(parent instanceof JComponent)) { - return null; - } - component = (JComponent) parent; - } - } - - @Override - public State mouseWheelMoved(Widget widget, WidgetMouseWheelEvent event) { - final Scene scene = widget.getScene(); - int amount = event.getWheelRotation(); - JScrollPane scrollPane = findScrollPane(scene.getView()); - Point viewPosition = null; - Point mouseLocation = scene.convertSceneToView(event.getPoint()); - int xOffset = 0; - int yOffset = 0; - Rectangle bounds = new Rectangle(scene.getBounds()); - Dimension componentSize = new Dimension(scene.getView().getPreferredSize()); - - if (scrollPane != null) { - viewPosition = new Point(scrollPane.getViewport().getViewPosition()); - xOffset = (mouseLocation.x - viewPosition.x); - yOffset = (mouseLocation.y - viewPosition.y); - viewPosition.x += xOffset; - viewPosition.y += yOffset; - } - - if (useAnimator) { - SceneAnimator sceneAnimator = scene.getSceneAnimator(); - synchronized (sceneAnimator) { - double zoom = sceneAnimator.isAnimatingZoomFactor() ? sceneAnimator.getTargetZoomFactor() : scene.getZoomFactor(); - while (amount > 0 && zoom / zoomMultiplier >= minFactor && zoom / zoomMultiplier <= maxFactor) { - zoom /= zoomMultiplier; - if (viewPosition != null) { - viewPosition.x /= zoomMultiplier; - viewPosition.y /= zoomMultiplier; - bounds.width /= zoomMultiplier; - bounds.height /= zoomMultiplier; - componentSize.width /= zoomMultiplier; - componentSize.height /= zoomMultiplier; - } - amount--; - } - while (amount < 0 && zoom * zoomMultiplier >= minFactor && zoom * zoomMultiplier <= maxFactor) { - zoom *= zoomMultiplier; - if (viewPosition != null) { - viewPosition.x *= zoomMultiplier; - viewPosition.y *= zoomMultiplier; - bounds.width *= zoomMultiplier; - bounds.height *= zoomMultiplier; - componentSize.width *= zoomMultiplier; - componentSize.height *= zoomMultiplier; - } - amount++; - } - sceneAnimator.animateZoomFactor(zoom); - } - } else { - double zoom = scene.getZoomFactor(); - while (amount > 0 && zoom / zoomMultiplier >= minFactor && zoom / zoomMultiplier <= maxFactor) { - zoom /= zoomMultiplier; - if (viewPosition != null) { - viewPosition.x /= zoomMultiplier; - viewPosition.y /= zoomMultiplier; - bounds.width /= zoomMultiplier; - bounds.height /= zoomMultiplier; - componentSize.width /= zoomMultiplier; - componentSize.height /= zoomMultiplier; - } - amount--; - } - while (amount < 0 && zoom * zoomMultiplier >= minFactor && zoom * zoomMultiplier <= maxFactor) { - zoom *= zoomMultiplier; - if (viewPosition != null) { - viewPosition.x *= zoomMultiplier; - viewPosition.y *= zoomMultiplier; - bounds.width *= zoomMultiplier; - bounds.height *= zoomMultiplier; - componentSize.width *= zoomMultiplier; - componentSize.height *= zoomMultiplier; - } - amount++; - } - scene.setZoomFactor(zoom); - } - - if (scrollPane != null) { - scene.validate(); // Call validate to update size of scene - Dimension size = scrollPane.getViewport().getExtentSize(); - viewPosition.x -= xOffset; - viewPosition.y -= yOffset; - scene.resolveBounds(scene.getLocation(), bounds); - scene.getView().setPreferredSize(componentSize); - scene.getView().revalidate(); - scene.getView().addNotify(); - scrollPane.getViewport().setViewPosition(viewPosition); - } - - return WidgetAction.State.CONSUMED; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Util/src/com/sun/hotspot/igv/util/Bundle.properties --- a/visualizer/Util/src/com/sun/hotspot/igv/util/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -OpenIDE-Module-Name=Util diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Util/src/com/sun/hotspot/igv/util/ColorIcon.java --- a/visualizer/Util/src/com/sun/hotspot/igv/util/ColorIcon.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.util; - -import java.awt.Color; -import java.awt.Component; -import java.awt.Graphics; -import javax.swing.Icon; - -/** - * - * @author Thomas Wuerthinger - */ -public class ColorIcon implements Icon { - - private Color color; - - public ColorIcon(Color c) { - color = c; - } - - @Override - public void paintIcon(Component c, Graphics g, int x, int y) { - g.setColor(color); - g.fillRect(x, y, 16, 16); - } - - @Override - public int getIconWidth() { - return 16; - } - - @Override - public int getIconHeight() { - return 16; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Util/src/com/sun/hotspot/igv/util/CompilationViewModel.java --- a/visualizer/Util/src/com/sun/hotspot/igv/util/CompilationViewModel.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ - -package com.sun.hotspot.igv.util; - -import com.sun.hotspot.igv.data.*; -import java.awt.Color; -import java.util.List; - -public class CompilationViewModel implements ChangedEventProvider { - - private final ChangedEvent changedEvent = new ChangedEvent<>(this); - private final RangeSliderModel model; - private final Group group; - - @Override - public ChangedEvent getChangedEvent() { - return changedEvent; - } - - public CompilationViewModel(RangeSliderModel model, Group group) { - this.model = model; - this.group = group; - model.getChangedEvent().addListener(rangeSliderChangedListener); - } - - private final ChangedListener rangeSliderChangedListener = new ChangedListener() { - @Override - public void changed(RangeSliderModel source) { - changedEvent.fire(); - } - }; - - public InputGraph getFirstSnapshot() { - return group.getGraphs().get(model.getFirstPosition()); - } - - public InputGraph getSecondSnapshot() { - return group.getGraphs().get(model.getSecondPosition()); - } - - public void setColors(List colors) { - model.setColors(colors); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Util/src/com/sun/hotspot/igv/util/DoubleClickAction.java --- a/visualizer/Util/src/com/sun/hotspot/igv/util/DoubleClickAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.util; - -import org.netbeans.api.visual.action.WidgetAction; -import org.netbeans.api.visual.widget.Widget; - -/** - * - * @author Thomas Wuerthinger - */ -public class DoubleClickAction extends WidgetAction.Adapter { - - private DoubleClickHandler handler; - - public DoubleClickAction(DoubleClickHandler handler) { - this.handler = handler; - } - - @Override - public WidgetAction.State mouseClicked(Widget widget, WidgetAction.WidgetMouseEvent event) { - if (event.getClickCount() > 1) { - handler.handleDoubleClick(widget, event); - return WidgetAction.State.CONSUMED; - } - return WidgetAction.State.REJECTED; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Util/src/com/sun/hotspot/igv/util/DoubleClickHandler.java --- a/visualizer/Util/src/com/sun/hotspot/igv/util/DoubleClickHandler.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.util; - -import org.netbeans.api.visual.action.WidgetAction.WidgetMouseEvent; -import org.netbeans.api.visual.widget.Widget; - -/** - * - * @author Thomas Wuerthinger - */ -public interface DoubleClickHandler { - - public void handleDoubleClick(Widget w, WidgetMouseEvent e); -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Util/src/com/sun/hotspot/igv/util/ExtendedSatelliteComponent.java --- a/visualizer/Util/src/com/sun/hotspot/igv/util/ExtendedSatelliteComponent.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,208 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.util; - -import java.awt.*; -import java.awt.event.*; -import javax.swing.JComponent; -import org.netbeans.api.visual.widget.Scene; - -/** - * @author David Kaspar - * @author Thomas Wuerthinger - */ -public class ExtendedSatelliteComponent extends JComponent implements MouseListener, MouseMotionListener, Scene.SceneListener, ComponentListener { - - private Scene scene; - private Image image; - private int imageWidth; - private int imageHeight; - - public ExtendedSatelliteComponent(Scene scene) { - this.scene = scene; - setDoubleBuffered(true); - setPreferredSize(new Dimension(128, 128)); - addMouseListener(this); - addMouseMotionListener(this); - } - - @Override - public void addNotify() { - super.addNotify(); - scene.addSceneListener(this); - JComponent viewComponent = scene.getView(); - if (viewComponent == null) { - viewComponent = scene.createView(); - } - viewComponent.addComponentListener(this); - repaint(); - } - - @Override - public void removeNotify() { - scene.getView().removeComponentListener(this); - scene.removeSceneListener(this); - super.removeNotify(); - } - - public void update() { - this.image = null; - repaint(); - } - - @Override - public void paint(Graphics g) { - Graphics2D gr = (Graphics2D) g; - super.paint(g); - Rectangle bounds = scene.getBounds(); - Dimension size = getSize(); - - double sx = bounds.width > 0 ? (double) size.width / bounds.width : 0.0; - double sy = bounds.width > 0 ? (double) size.height / bounds.height : 0.0; - double scale = Math.min(sx, sy); - - int vw = (int) (scale * bounds.width); - int vh = (int) (scale * bounds.height); - int vx = (size.width - vw) / 2; - int vy = (size.height - vh) / 2; - - - if (image == null || vw != imageWidth || vh != imageHeight) { - - imageWidth = vw; - imageHeight = vh; - image = this.createImage(imageWidth, imageHeight); - Graphics2D ig = (Graphics2D) image.getGraphics(); - ig.scale(scale, scale); - scene.paint(ig); - } - - gr.drawImage(image, vx, vy, this); - - JComponent component = scene.getView(); - double zoomFactor = scene.getZoomFactor(); - Rectangle viewRectangle = component != null ? component.getVisibleRect() : null; - if (viewRectangle != null) { - Rectangle window = new Rectangle( - (int) ((double) viewRectangle.x * scale / zoomFactor), - (int) ((double) viewRectangle.y * scale / zoomFactor), - (int) ((double) viewRectangle.width * scale / zoomFactor), - (int) ((double) viewRectangle.height * scale / zoomFactor)); - window.translate(vx, vy); - gr.setColor(new Color(200, 200, 200, 128)); - gr.fill(window); - gr.setColor(Color.BLACK); - gr.drawRect(window.x, window.y, window.width - 1, window.height - 1); - } - } - - @Override - public void mouseClicked(MouseEvent e) { - } - - @Override - public void mousePressed(MouseEvent e) { - moveVisibleRect(e.getPoint()); - } - - @Override - public void mouseReleased(MouseEvent e) { - moveVisibleRect(e.getPoint()); - } - - @Override - public void mouseEntered(MouseEvent e) { - } - - @Override - public void mouseExited(MouseEvent e) { - } - - @Override - public void mouseDragged(MouseEvent e) { - moveVisibleRect(e.getPoint()); - } - - @Override - public void mouseMoved(MouseEvent e) { - } - - private void moveVisibleRect(Point center) { - JComponent component = scene.getView(); - if (component == null) { - return; - } - double zoomFactor = scene.getZoomFactor(); - Rectangle bounds = scene.getBounds(); - Dimension size = getSize(); - - double sx = bounds.width > 0 ? (double) size.width / bounds.width : 0.0; - double sy = bounds.width > 0 ? (double) size.height / bounds.height : 0.0; - double scale = Math.min(sx, sy); - - int vw = (int) (scale * bounds.width); - int vh = (int) (scale * bounds.height); - int vx = (size.width - vw) / 2; - int vy = (size.height - vh) / 2; - - int cx = (int) ((double) (center.x - vx) / scale * zoomFactor); - int cy = (int) ((double) (center.y - vy) / scale * zoomFactor); - - Rectangle visibleRect = component.getVisibleRect(); - visibleRect.x = cx - visibleRect.width / 2; - visibleRect.y = cy - visibleRect.height / 2; - component.scrollRectToVisible(visibleRect); - - } - - @Override - public void sceneRepaint() { - } - - @Override - public void sceneValidating() { - } - - @Override - public void sceneValidated() { - } - - @Override - public void componentResized(ComponentEvent e) { - repaint(); - } - - @Override - public void componentMoved(ComponentEvent e) { - repaint(); - } - - @Override - public void componentShown(ComponentEvent e) { - } - - @Override - public void componentHidden(ComponentEvent e) { - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Util/src/com/sun/hotspot/igv/util/ExtendedSelectAction.java --- a/visualizer/Util/src/com/sun/hotspot/igv/util/ExtendedSelectAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.util; - -import java.awt.event.MouseEvent; -import javax.swing.JPanel; -import org.netbeans.api.visual.action.ActionFactory; -import org.netbeans.api.visual.action.SelectProvider; -import org.netbeans.api.visual.action.WidgetAction; -import org.netbeans.api.visual.action.WidgetAction.State; -import org.netbeans.api.visual.action.WidgetAction.WidgetKeyEvent; -import org.netbeans.api.visual.action.WidgetAction.WidgetMouseEvent; -import org.netbeans.api.visual.widget.Widget; - -/** - * - * @author Thomas Wuerthinger - */ -public class ExtendedSelectAction extends WidgetAction.Adapter { - - private WidgetAction innerAction; - private JPanel panel; - - public ExtendedSelectAction(SelectProvider provider) { - innerAction = ActionFactory.createSelectAction(provider); - panel = new JPanel(); - } - - @Override - public State mousePressed(Widget widget, WidgetMouseEvent event) { - // TODO: Solve this differently? - if (event.getButton() != MouseEvent.BUTTON2) { - return innerAction.mousePressed(widget, new WidgetMouseEvent(event.getEventID(), new MouseEvent(panel, (int) event.getEventID(), event.getWhen(), event.getModifiersEx(), event.getPoint().x, event.getPoint().y, event.getClickCount(), event.isPopupTrigger(), MouseEvent.BUTTON1))); - } else { - return super.mousePressed(widget, event); - } - } - - @Override - public State mouseReleased(Widget widget, WidgetMouseEvent event) { - return innerAction.mouseReleased(widget, event); - } - - @Override - public State keyTyped(Widget widget, WidgetKeyEvent event) { - return innerAction.keyTyped(widget, event); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Util/src/com/sun/hotspot/igv/util/PropertiesSheet.java --- a/visualizer/Util/src/com/sun/hotspot/igv/util/PropertiesSheet.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* - * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 com.sun.hotspot.igv.util; - -import com.sun.hotspot.igv.data.Properties; -import com.sun.hotspot.igv.data.Property; -import java.lang.reflect.InvocationTargetException; -import org.openide.nodes.Node; -import org.openide.nodes.Sheet; - -/** - * - * @author Thomas Wuerthinger - */ -public class PropertiesSheet { - - public static void initializeSheet(final Properties properties, Sheet s) { - - Sheet.Set set1 = Sheet.createPropertiesSet(); - set1.setDisplayName("Properties"); - for (final Property p : properties) { - Node.Property prop = new Node.Property(String.class) { - - @Override - public boolean canRead() { - return true; - } - - @Override - public String getValue() throws IllegalAccessException, InvocationTargetException { - return p.getValue(); - } - - @Override - public boolean canWrite() { - return false; - } - - @Override - public void setValue(String arg0) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - properties.setProperty(p.getName(), arg0); - } - }; - prop.setName(p.getName()); - set1.put(prop); - } - s.put(set1); - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Util/src/com/sun/hotspot/igv/util/RangeSlider.java --- a/visualizer/Util/src/com/sun/hotspot/igv/util/RangeSlider.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,263 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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 com.sun.hotspot.igv.util; - -import com.sun.hotspot.igv.data.ChangedListener; -import java.awt.*; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.MouseMotionListener; -import java.util.List; -import javax.swing.JComponent; - -public final class RangeSlider extends JComponent { - - public static final int BAR_THICKNESS = 2; - public static final int BAR_CIRCLE_SIZE = 9; - public static final int MOUSE_ENDING_OFFSET = 3; - public static final Color BACKGROUND_COLOR = Color.white; - public static final Color BAR_COLOR = Color.black; - public static final Color BAR_SELECTION_COLOR = new Color(255, 0, 0, 120); - public static final Color TEXT_SELECTION_COLOR = new Color(200, 200, 200, 255); - public static final int ITEM_HEIGHT = 30; - public static final int ITEM_WIDTH = 30; - private RangeSliderModel model; - private Point startPoint; - private RangeSliderModel tempModel; - private Point lastMouseMove; - - public RangeSlider(RangeSliderModel newModel) { - this.addMouseMotionListener(mouseMotionListener); - this.addMouseListener(mouseListener); - setModel(newModel); - } - - private RangeSliderModel getPaintingModel() { - if (tempModel != null) { - return tempModel; - } - return model; - } - - @Override - public Dimension getPreferredSize() { - if (getPaintingModel() != null) { - Graphics g = this.getGraphics(); - int maxWidth = 0; - List list = getPaintingModel().getPositions(); - for (int i = 0; i < list.size(); i++) { - String curS = list.get(i); - if (curS != null && curS.length() > 0) { - FontMetrics metrics = g.getFontMetrics(); - Rectangle bounds = metrics.getStringBounds(curS, g).getBounds(); - maxWidth = Math.max(maxWidth, (int) bounds.getWidth()); - } - } - return new Dimension(maxWidth + ITEM_WIDTH, ITEM_HEIGHT * list.size()); - } - return super.getPreferredSize(); - } - private ChangedListener modelChangedListener = new ChangedListener() { - - @Override - public void changed(RangeSliderModel source) { - update(); - } - }; - - private void update() { - this.revalidate(); - this.repaint(); - } - - private Rectangle getItemBounds(int index) { - Rectangle r = new Rectangle(); - r.width = ITEM_WIDTH; - r.height = ITEM_HEIGHT; - r.x = 0; - r.y = ITEM_HEIGHT * index; - return r; - } - - @Override - public void paint(Graphics g) { - super.paint(g); - Graphics2D g2 = (Graphics2D) g; - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_ON); - int width = getWidth(); - int height = getHeight(); - - g2.setColor(BACKGROUND_COLOR); - g2.fillRect(0, 0, width, height); - - // Nothing to paint? - if (getPaintingModel() == null || getPaintingModel().getPositions().isEmpty()) { - return; - } - - paintSelected(g2); - paintBar(g2); - - } - - private void fillRect(Graphics2D g, int startX, int startY, int endY, int thickness) { - g.fillRect(startX - thickness / 2, startY, thickness, endY - startY); - } - - private void paintBar(Graphics2D g) { - List list = getPaintingModel().getPositions(); - - g.setColor(BAR_COLOR); - Rectangle firstItemBounds = getItemBounds(0); - Rectangle lastItemBounds = getItemBounds(list.size() - 1); - fillRect(g, (int) firstItemBounds.getCenterX(), (int) firstItemBounds.getCenterY(), (int) lastItemBounds.getCenterY(), BAR_THICKNESS); - - for (int i = 0; i < list.size(); i++) { - Rectangle curItemBounds = getItemBounds(i); - g.setColor(getPaintingModel().getColors().get(i)); - g.fillOval((int) curItemBounds.getCenterX() - BAR_CIRCLE_SIZE / 2, (int) curItemBounds.getCenterY() - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE); - g.setColor(Color.black); - g.drawOval((int) curItemBounds.getCenterX() - BAR_CIRCLE_SIZE / 2, (int) curItemBounds.getCenterY() - BAR_CIRCLE_SIZE / 2, BAR_CIRCLE_SIZE, BAR_CIRCLE_SIZE); - - String curS = list.get(i); - if (curS != null && curS.length() > 0) { - FontMetrics metrics = g.getFontMetrics(); - Rectangle bounds = metrics.getStringBounds(curS, g).getBounds(); - g.setColor(Color.black); - g.drawString(curS, curItemBounds.x + curItemBounds.width, (int) curItemBounds.getCenterY() + bounds.height / 2 - 2); - } - } - - } - - private void paintSelected(Graphics2D g) { - List list = getPaintingModel().getPositions(); - for (int i = 0; i < list.size(); i++) { - Rectangle curItemBounds = getItemBounds(i); - if (lastMouseMove != null && curItemBounds.y <= lastMouseMove.y && curItemBounds.y + curItemBounds.height > lastMouseMove.y) { - g.setColor(TEXT_SELECTION_COLOR); - g.fillRect(0, curItemBounds.y, getWidth(), curItemBounds.height); - } - } - final Rectangle barBounds = getBarBounds(); - - g.setColor(BAR_SELECTION_COLOR); - g.fill(barBounds); - } - - private Rectangle getBarBounds() { - final Rectangle startItemBounds = getItemBounds(getPaintingModel().getFirstPosition()); - final Rectangle endItemBounds = getItemBounds(getPaintingModel().getSecondPosition()); - int startY = startItemBounds.y; - int endY = endItemBounds.y + endItemBounds.height; - return new Rectangle(0, startY, getWidth(), endY - startY); - } - - private int getIndexFromPosition(int y) { - for (int i = 0; i < getPaintingModel().getPositions().size() - 1; i++) { - Rectangle bounds = getItemBounds(i); - if (bounds.y <= y && bounds.y + bounds.height >= y) { - return i; - } - } - return getPaintingModel().getPositions().size() - 1; - } - private final MouseMotionListener mouseMotionListener = new MouseMotionListener() { - - @Override - public void mouseDragged(MouseEvent e) { - if (startPoint != null) { - int startIndex = getIndexFromPosition(startPoint.y); - int curIndex = getIndexFromPosition(e.getPoint().y); - tempModel.setPositions(startIndex, curIndex); - } - } - - @Override - public void mouseMoved(MouseEvent e) { - lastMouseMove = e.getPoint(); - update(); - } - }; - private final MouseListener mouseListener = new MouseListener() { - - @Override - public void mouseClicked(MouseEvent e) { - if (model != null) { - int index = getIndexFromPosition(e.getPoint().y); - model.setPositions(index, index); - } - } - - @Override - public void mousePressed(MouseEvent e) { - if (model != null) { - int index = getIndexFromPosition(e.getPoint().y); - startPoint = e.getPoint(); - tempModel = model.copy(); - tempModel.getChangedEvent().addListener(modelChangedListener); - tempModel.setPositions(index, index); - } - } - - @Override - public void mouseReleased(MouseEvent e) { - if (tempModel != null) { - model.setPositions(tempModel.getFirstPosition(), tempModel.getSecondPosition()); - tempModel = null; - startPoint = null; - } - } - - @Override - public void mouseEntered(MouseEvent e) { - } - - @Override - public void mouseExited(MouseEvent e) { - lastMouseMove = null; - repaint(); - } - }; - - public RangeSliderModel getModel() { - return model; - } - - public void setModel(RangeSliderModel newModel) { - if (newModel != this.model) { - if (this.model != null) { - this.model.getChangedEvent().removeListener(modelChangedListener); - } - this.model = newModel; - if (newModel != null) { - newModel.getChangedEvent().addListener(modelChangedListener); - } - this.tempModel = null; - update(); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/Util/src/com/sun/hotspot/igv/util/RangeSliderModel.java --- a/visualizer/Util/src/com/sun/hotspot/igv/util/RangeSliderModel.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +0,0 @@ -/* - * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 com.sun.hotspot.igv.util; - -import com.sun.hotspot.igv.data.ChangedEvent; -import com.sun.hotspot.igv.data.ChangedEventProvider; -import java.awt.Color; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * - * @author Thomas Wuerthinger - */ -public class RangeSliderModel implements ChangedEventProvider { - - // Warning: Update setData method if fields are added - private ChangedEvent changedEvent; - private List positions; - private int firstPosition; - private int secondPosition; - private List colors; - - public void setData(RangeSliderModel model) { - boolean changed = false; - changed |= (positions != model.positions); - positions = model.positions; - changed |= (firstPosition != model.firstPosition); - firstPosition = model.firstPosition; - changed |= (secondPosition != model.secondPosition); - secondPosition = model.secondPosition; - changed |= (colors != model.colors); - colors = model.colors; - if (changed) { - changedEvent.fire(); - } - } - - public RangeSliderModel(List positions) { - assert positions.size() > 0; - this.changedEvent = new ChangedEvent<>(this); - setPositions(positions); - } - - protected final void setPositions(List positions) { - this.positions = positions; - colors = new ArrayList<>(); - for (int i = 0; i < positions.size(); i++) { - colors.add(Color.black); - } - firstPosition = Math.min(firstPosition, positions.size() - 1); - secondPosition = Math.min(secondPosition, positions.size() - 1); - changedEvent.fire(); - } - - public void setColors(List colors) { - this.colors = colors; - changedEvent.fire(); - } - - public List getColors() { - return colors; - } - - public RangeSliderModel copy() { - RangeSliderModel newModel = new RangeSliderModel(positions); - newModel.setData(this); - return newModel; - } - - public List getPositions() { - return Collections.unmodifiableList(positions); - } - - public int getFirstPosition() { - return firstPosition; - } - - public int getSecondPosition() { - return secondPosition; - } - - public void setPositions(int fp, int sp) { - assert fp >= 0 && fp < positions.size(); - assert sp >= 0 && sp < positions.size(); - firstPosition = fp; - secondPosition = sp; - ensureOrder(); - changedEvent.fire(); - } - - private void ensureOrder() { - if (secondPosition < firstPosition) { - int tmp = secondPosition; - secondPosition = firstPosition; - firstPosition = tmp; - } - } - - @Override - public ChangedEvent getChangedEvent() { - return changedEvent; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/build.xml --- a/visualizer/View/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project com.sun.hotspot.igv.view. - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/manifest.mf --- a/visualizer/View/manifest.mf Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: com.sun.hotspot.igv.view -OpenIDE-Module-Layer: com/sun/hotspot/igv/view/layer.xml -OpenIDE-Module-Localizing-Bundle: com/sun/hotspot/igv/view/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/nbproject/build-impl.xml --- a/visualizer/View/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/nbproject/genfiles.properties --- a/visualizer/View/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -build.xml.data.CRC32=2de95ef6 -build.xml.script.CRC32=31afe4b1 -build.xml.stylesheet.CRC32=79c3b980 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=2de95ef6 -nbproject/build-impl.xml.script.CRC32=fa7a4119 -nbproject/build-impl.xml.stylesheet.CRC32=deb65f65 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/nbproject/platform.properties --- a/visualizer/View/nbproject/platform.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -# Deprecated since 5.0u1; for compatibility with 5.0: -disabled.clusters=\ - apisupport1,\ - harness,\ - ide8,\ - java1,\ - nb6.0,\ - profiler2 -disabled.modules=\ - org.netbeans.core.execution,\ - org.netbeans.core.multiview,\ - org.netbeans.core.output2,\ - org.netbeans.modules.applemenu,\ - org.netbeans.modules.autoupdate.services,\ - org.netbeans.modules.autoupdate.ui,\ - org.netbeans.modules.core.kit,\ - org.netbeans.modules.favorites,\ - org.netbeans.modules.javahelp,\ - org.netbeans.modules.masterfs,\ - org.netbeans.modules.options.keymap,\ - org.netbeans.modules.sendopts,\ - org.netbeans.modules.templates,\ - org.openide.compat,\ - org.openide.execution,\ - org.openide.util.enumerations -enabled.clusters=\ - platform7 -nbjdk.active=JDK_1.6 -nbplatform.active=default diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/nbproject/project.properties --- a/visualizer/View/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -javac.source=1.7 -javac.compilerargs=-Xlint -Xlint:-serial diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/nbproject/project.xml --- a/visualizer/View/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,183 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - com.sun.hotspot.igv.view - - - - com.oracle.graal.visualizer.editor - - - - 1.0 - - - - com.oracle.graal.visualizer.sharedactions - - - - 1.0 - - - - com.sun.hotspot.igv.data - - - - 1.0 - - - - com.sun.hotspot.igv.difference - - - - 1.0 - - - - com.sun.hotspot.igv.filter - - - - 1.0 - - - - com.sun.hotspot.igv.graph - - - - 1.0 - - - - com.sun.hotspot.igv.hierarchicallayout - - - - 1.0 - - - - com.sun.hotspot.igv.layout - - - - 1.0 - - - - com.sun.hotspot.igv.settings - - - - 1.0 - - - - com.sun.hotspot.igv.svg - - - - 1.0 - - - - com.sun.hotspot.igv.util - - - - 1.0 - - - - org.netbeans.api.visual - - - - 2.27.1 - - - - org.netbeans.spi.quicksearch - - - - 1.0 - - - - org.openide.actions - - - - 6.21.1 - - - - org.openide.awt - - - - 7.30.1 - - - - org.openide.dialogs - - - - 7.18.1 - - - - org.openide.loaders - - - - 7.20.1 - - - - org.openide.nodes - - - - 7.20.1 - - - - org.openide.util - - - - 8.14.1 - - - - org.openide.util.lookup - - - - 8.6.1 - - - - org.openide.windows - - - - 6.39.1 - - - - - com.sun.hotspot.igv.view - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/nbproject/suite.properties --- a/visualizer/View/nbproject/suite.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -suite.dir=${basedir}/.. diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/META-INF/services/com.oracle.graal.visualizer.editor.CompilationViewerFactory --- a/visualizer/View/src/META-INF/services/com.oracle.graal.visualizer.editor.CompilationViewerFactory Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -com.sun.hotspot.igv.view.scene.GraphCompilationViewerFactory diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/Bundle.properties --- a/visualizer/View/src/com/sun/hotspot/igv/view/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -OpenIDE-Module-Name=View \ No newline at end of file diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/actions/Bundle.properties --- a/visualizer/View/src/com/sun/hotspot/igv/view/actions/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -CTL_EditorAction=Open Editor Window -CTL_EnableBlockLayoutAction=Enable block layout -CTL_NodeFindAction=Find -CTL_ExportAction=Export current graph... diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/actions/ExpandPredecessorsAction.java --- a/visualizer/View/src/com/sun/hotspot/igv/view/actions/ExpandPredecessorsAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.view.actions; - -import com.oracle.graal.visualizer.editor.EditorTopComponent; -import org.openide.util.HelpCtx; -import org.openide.util.actions.CallableSystemAction; - -/** - * - * @author Thomas Wuerthinger - */ -public final class ExpandPredecessorsAction extends CallableSystemAction { - - @Override - public void performAction() { - EditorTopComponent editor = EditorTopComponent.getActive(); - if (editor != null) { - //editor.expandPredecessors(); - } - } - - @Override - public String getName() { - return "Expand Above"; - } - - @Override - protected void initialize() { - super.initialize(); - } - - @Override - public HelpCtx getHelpCtx() { - return HelpCtx.DEFAULT_HELP; - } - - @Override - protected boolean asynchronous() { - return false; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/actions/ExpandSuccessorsAction.java --- a/visualizer/View/src/com/sun/hotspot/igv/view/actions/ExpandSuccessorsAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.view.actions; - -import com.oracle.graal.visualizer.editor.EditorTopComponent; -import org.openide.util.HelpCtx; -import org.openide.util.actions.CallableSystemAction; - -/** - * - * @author Thomas Wuerthinger - */ -public final class ExpandSuccessorsAction extends CallableSystemAction { - - @Override - public void performAction() { - EditorTopComponent editor = EditorTopComponent.getActive(); - if (editor != null) { - //editor.expandSuccessors(); - } - } - - @Override - public String getName() { - return "Expand Below"; - } - - @Override - protected void initialize() { - super.initialize(); - } - - @Override - public HelpCtx getHelpCtx() { - return HelpCtx.DEFAULT_HELP; - } - - @Override - protected boolean asynchronous() { - return false; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/actions/ExtractAction.java --- a/visualizer/View/src/com/sun/hotspot/igv/view/actions/ExtractAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.view.actions; - -import com.oracle.graal.visualizer.editor.EditorTopComponent; -import java.awt.Event; -import java.awt.event.KeyEvent; -import javax.swing.Action; -import javax.swing.KeyStroke; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.awt.ActionRegistration; -import org.openide.util.HelpCtx; -import org.openide.util.actions.CallableSystemAction; - -/** - * - * @author Thomas Wuerthinger - */ -@ActionID(id = "com.sun.hotspot.igv.view.actions.ExtractAction", category = "View") -@ActionRegistration(displayName = "Extract nodes") -@ActionReference(path = "Menu/View", position = 300) -public final class ExtractAction extends CallableSystemAction { - - @Override - public void performAction() { - EditorTopComponent editor = EditorTopComponent.getActive(); - if (editor != null) { - //editor.extract(); - } - } - - public ExtractAction() { - putValue(Action.SHORT_DESCRIPTION, "Extract current set of selected nodes"); - putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_X, Event.CTRL_MASK, false)); - } - - @Override - public String getName() { - return "Extract action"; - } - - @Override - protected void initialize() { - super.initialize(); - } - - @Override - public HelpCtx getHelpCtx() { - return HelpCtx.DEFAULT_HELP; - } - - @Override - protected boolean asynchronous() { - return false; - } - - @Override - protected String iconResource() { - return "com/sun/hotspot/igv/view/images/extract.gif"; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/actions/HideAction.java --- a/visualizer/View/src/com/sun/hotspot/igv/view/actions/HideAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.view.actions; - -import com.oracle.graal.visualizer.editor.EditorTopComponent; -import java.awt.Event; -import java.awt.event.KeyEvent; -import javax.swing.Action; -import javax.swing.KeyStroke; -import org.openide.awt.ActionID; -import org.openide.awt.ActionReference; -import org.openide.awt.ActionRegistration; -import org.openide.util.HelpCtx; -import org.openide.util.actions.CallableSystemAction; - -/** - * - * @author Thomas Wuerthinger - */ -@ActionID(id = "com.sun.hotspot.igv.view.actions.HideAction", category = "View") -@ActionRegistration(displayName = "Hide nodes") -@ActionReference(path = "Menu/View", position = 400) -public final class HideAction extends CallableSystemAction { - - @Override - public void performAction() { - EditorTopComponent editor = EditorTopComponent.getActive(); - if (editor != null) { - //editor.hideNodes(); - } - } - - public HideAction() { - putValue(Action.SHORT_DESCRIPTION, "Hide selected nodes"); - putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_H, Event.CTRL_MASK, false)); - } - - @Override - public String getName() { - return "Hide"; - } - - @Override - protected void initialize() { - super.initialize(); - } - - @Override - public HelpCtx getHelpCtx() { - return HelpCtx.DEFAULT_HELP; - } - - @Override - protected boolean asynchronous() { - return false; - } - - @Override - protected String iconResource() { - return "com/sun/hotspot/igv/view/images/hide.gif"; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/actions/MouseOverAction.java --- a/visualizer/View/src/com/sun/hotspot/igv/view/actions/MouseOverAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.view.actions; - -import org.netbeans.api.visual.action.HoverProvider; -import org.netbeans.api.visual.action.WidgetAction; -import org.netbeans.api.visual.action.WidgetAction.State; -import org.netbeans.api.visual.widget.Widget; - -/** - * - * @author Thomas Wuerthinger - */ -public class MouseOverAction extends WidgetAction.Adapter { - - private long eventID = Integer.MIN_VALUE; - private HoverProvider provider; - - public MouseOverAction(HoverProvider provider) { - this.provider = provider; - } - - @Override - public State mouseMoved(Widget widget, WidgetMouseEvent event) { - long id = event.getEventID(); - if (id != eventID) { - eventID = id; - provider.widgetHovered(widget); - } - return State.REJECTED; - } - - @Override - public State mouseExited(Widget widget, WidgetMouseEvent event) { - provider.widgetHovered(null); - return State.REJECTED; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/actions/PredSuccAction.java --- a/visualizer/View/src/com/sun/hotspot/igv/view/actions/PredSuccAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.view.actions; - -import java.awt.event.ActionEvent; -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.ImageIcon; -import org.openide.util.ImageUtilities; - -/** - * - * @author Thomas Wuerthinger - */ -public class PredSuccAction extends AbstractAction { - - private boolean state; - public static final String STATE = "state"; - - public PredSuccAction() { - state = true; - putValue(AbstractAction.SMALL_ICON, new ImageIcon(ImageUtilities.loadImage(iconResource()))); - putValue(STATE, true); - putValue(Action.SHORT_DESCRIPTION, "Show neighboring nodes of fully visible nodes semi-transparent"); - } - - @Override - public void actionPerformed(ActionEvent ev) { - this.state = !state; - this.putValue(STATE, state); - } - - protected String iconResource() { - return "com/sun/hotspot/igv/view/images/predsucc.gif"; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/images/blocks.gif Binary file visualizer/View/src/com/sun/hotspot/igv/view/images/blocks.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/images/expand.gif Binary file visualizer/View/src/com/sun/hotspot/igv/view/images/expand.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/images/extract.gif Binary file visualizer/View/src/com/sun/hotspot/igv/view/images/extract.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/images/hide.gif Binary file visualizer/View/src/com/sun/hotspot/igv/view/images/hide.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/images/overview.png Binary file visualizer/View/src/com/sun/hotspot/igv/view/images/overview.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/images/pan_mode.png Binary file visualizer/View/src/com/sun/hotspot/igv/view/images/pan_mode.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/images/predsucc.gif Binary file visualizer/View/src/com/sun/hotspot/igv/view/images/predsucc.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/images/selection_mode.png Binary file visualizer/View/src/com/sun/hotspot/igv/view/images/selection_mode.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/images/zoom_in.png Binary file visualizer/View/src/com/sun/hotspot/igv/view/images/zoom_in.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/images/zoom_out.png Binary file visualizer/View/src/com/sun/hotspot/igv/view/images/zoom_out.png has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/layer.xml --- a/visualizer/View/src/com/sun/hotspot/igv/view/layer.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/scene/CustomizablePanWidgetAction.java --- a/visualizer/View/src/com/sun/hotspot/igv/view/scene/CustomizablePanWidgetAction.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,146 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved. - * - * Oracle and Java are registered trademarks of Oracle and/or its affiliates. - * Other names may be trademarks of their respective owners. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common - * Development and Distribution License("CDDL") (collectively, the - * "License"). You may not use this file except in compliance with the - * License. You can obtain a copy of the License at - * http://www.netbeans.org/cddl-gplv2.html - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the - * specific language governing permissions and limitations under the - * License. When distributing the software, include this License Header - * Notice in each file and include the License file at - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the GPL Version 2 section of the License file that - * accompanied this code. If applicable, add the following below the - * License Header, with the fields enclosed by brackets [] replaced by - * your own identifying information: - * "Portions Copyrighted [year] [name of copyright owner]" - * - * Contributor(s): - * - * The Original Software is NetBeans. The Initial Developer of the Original - * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun - * Microsystems, Inc. All Rights Reserved. - * - * If you wish your version of this file to be governed by only the CDDL - * or only the GPL Version 2, indicate your decision by adding - * "[Contributor] elects to include this software in this distribution - * under the [CDDL or GPL Version 2] license." If you do not indicate a - * single choice of license, a recipient has the option to distribute - * your version of this file under either the CDDL, the GPL Version 2 or - * to extend the choice of license to its licensees as provided above. - * However, if you add GPL Version 2 code and therefore, elected the GPL - * Version 2 license, then the option applies only if the new code is - * made subject to such option by the copyright holder. - */ -package com.sun.hotspot.igv.view.scene; - -import java.awt.Container; -import java.awt.Point; -import java.awt.Rectangle; -import javax.swing.JComponent; -import javax.swing.JScrollPane; -import javax.swing.SwingUtilities; -import org.netbeans.api.visual.action.WidgetAction; -import org.netbeans.api.visual.action.WidgetAction.State; -import org.netbeans.api.visual.action.WidgetAction.WidgetMouseEvent; -import org.netbeans.api.visual.widget.Scene; -import org.netbeans.api.visual.widget.Widget; - -/** - * @author David Kaspar - * @author Peter Hofer - */ -public class CustomizablePanWidgetAction extends WidgetAction.LockedAdapter { - private boolean enabled = true; - - private Scene scene; - private JScrollPane scrollPane; - private Point lastLocation; - - private final int modifiersExMask; - private final int modifiersEx; - - public CustomizablePanWidgetAction(int modifiersExMask, int modifiersEx) { - this.modifiersExMask = modifiersExMask; - this.modifiersEx = modifiersEx; - } - - @Override - protected boolean isLocked() { - return scrollPane != null; - } - - public void setEnabled(boolean enabled) { - if (this.enabled != enabled) { - if (isLocked()) - throw new IllegalStateException(); - - this.enabled = enabled; - } - } - - @Override - public State mousePressed (Widget widget, WidgetMouseEvent event) { - if (isLocked ()) - return State.createLocked (widget, this); - if (enabled && (event.getModifiersEx() & modifiersExMask) == modifiersEx) { - scene = widget.getScene (); - scrollPane = findScrollPane (scene.getView ()); - if (scrollPane != null) { - lastLocation = scene.convertSceneToView (widget.convertLocalToScene (event.getPoint ())); - SwingUtilities.convertPointToScreen (lastLocation, scene.getView ()); - return State.createLocked (widget, this); - } - } - return State.REJECTED; - } - - private JScrollPane findScrollPane (JComponent component) { - for (;;) { - if (component == null) - return null; - if (component instanceof JScrollPane) - return ((JScrollPane) component); - Container parent = component.getParent (); - if (! (parent instanceof JComponent)) - return null; - component = (JComponent) parent; - } - } - - @Override - public State mouseReleased (Widget widget, WidgetMouseEvent event) { - boolean state = pan (widget, event.getPoint ()); - if (state) - scrollPane = null; - return state ? State.createLocked (widget, this) : State.REJECTED; - } - - @Override - public State mouseDragged (Widget widget, WidgetMouseEvent event) { - return pan (widget, event.getPoint ()) ? State.createLocked (widget, this) : State.REJECTED; - } - - private boolean pan (Widget widget, Point newLocation) { - if (scrollPane == null || scene != widget.getScene ()) - return false; - newLocation = scene.convertSceneToView (widget.convertLocalToScene (newLocation)); - SwingUtilities.convertPointToScreen (newLocation, scene.getView ()); - JComponent view = scene.getView (); - Rectangle rectangle = view.getVisibleRect (); - rectangle.x += lastLocation.x - newLocation.x; - rectangle.y += lastLocation.y - newLocation.y; - view.scrollRectToVisible (rectangle); - lastLocation = newLocation; - return true; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/scene/DiagramScene.java --- a/visualizer/View/src/com/sun/hotspot/igv/view/scene/DiagramScene.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,964 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.view.scene; - -import com.oracle.graal.visualizer.editor.DiagramViewModel; -import com.oracle.graal.visualizer.sharedactions.ExportSVGCookie; -import com.oracle.graal.visualizer.sharedactions.ZoomCookie; -import com.sun.hotspot.igv.data.ChangedListener; -import com.sun.hotspot.igv.data.Pair; -import com.sun.hotspot.igv.data.Properties; -import com.sun.hotspot.igv.graph.*; -import com.sun.hotspot.igv.hierarchicallayout.HierarchicalLayoutManager; -import com.sun.hotspot.igv.layout.LayoutGraph; -import com.sun.hotspot.igv.util.ColorIcon; -import com.sun.hotspot.igv.util.DoubleClickAction; -import com.sun.hotspot.igv.util.PropertiesSheet; -import com.sun.hotspot.igv.view.widgets.*; -import java.awt.*; -import java.awt.event.*; -import java.util.List; -import java.util.*; -import javax.swing.*; -import org.netbeans.api.visual.action.*; -import org.netbeans.api.visual.animator.SceneAnimator; -import org.netbeans.api.visual.layout.LayoutFactory; -import org.netbeans.api.visual.model.*; -import org.netbeans.api.visual.widget.LayerWidget; -import org.netbeans.api.visual.widget.Widget; -import org.openide.nodes.AbstractNode; -import org.openide.nodes.Children; -import org.openide.nodes.Sheet; -import org.openide.util.Lookup; -import org.openide.util.lookup.AbstractLookup; -import org.openide.util.lookup.InstanceContent; - -public class DiagramScene extends ObjectScene implements ExportSVGCookie, ZoomCookie { - - private CustomizablePanWidgetAction panAction; - private WidgetAction hoverAction; - private WidgetAction selectAction; - private Lookup lookup; - private InstanceContent content; - private Action[] actions; - private LayerWidget connectionLayer; - private JScrollPane scrollPane; - private LayerWidget mainLayer; - private LayerWidget blockLayer; - private Widget topLeft; - private Widget bottomRight; - private DiagramViewModel model; - private WidgetAction zoomAction; - private boolean rebuilding; - /** - * The alpha level of partially visible figures. - */ - public static final float ALPHA = 0.4f; - /** - * The offset of the graph to the border of the window showing it. - */ - public static final int BORDER_SIZE = 20; - public static final int UNDOREDO_LIMIT = 100; - public static final int SCROLL_UNIT_INCREMENT = 80; - public static final int SCROLL_BLOCK_INCREMENT = 400; - public static final float ZOOM_MAX_FACTOR = 3.0f; - public static final float ZOOM_MIN_FACTOR = 0.0f;//0.15f; - public static final float ZOOM_INCREMENT = 1.5f; - public static final int SLOT_OFFSET = 6; - public static final int ANIMATION_LIMIT = 40; - private PopupMenuProvider popupMenuProvider = new PopupMenuProvider() { - - @Override - public JPopupMenu getPopupMenu(Widget widget, Point localLocation) { - return DiagramScene.this.createPopupMenu(); - } - }; - private RectangularSelectDecorator rectangularSelectDecorator = new RectangularSelectDecorator() { - - @Override - public Widget createSelectionWidget() { - Widget widget = new Widget(DiagramScene.this); - widget.setBorder(BorderFactory.createLineBorder(Color.black, 2)); - widget.setForeground(Color.red); - return widget; - } - }; - - @SuppressWarnings("unchecked") - public T getWidget(Object o) { - Widget w = this.findWidget(o); - return (T) w; - } - - @SuppressWarnings("unchecked") - public T getWidget(Object o, Class klass) { - Widget w = this.findWidget(o); - return (T) w; - } - - public void zoomOut() { - double zoom = getZoomFactor(); - Point viewPosition = getScrollPane().getViewport().getViewPosition(); - double newZoom = zoom / DiagramScene.ZOOM_INCREMENT; - if (newZoom > DiagramScene.ZOOM_MIN_FACTOR) { - setZoomFactor(newZoom); - validate(); - getScrollPane().getViewport().setViewPosition(new Point((int) (viewPosition.x / DiagramScene.ZOOM_INCREMENT), (int) (viewPosition.y / DiagramScene.ZOOM_INCREMENT))); - } - } - - public void zoomIn() { - - double zoom = getZoomFactor(); - Point viewPosition = getScrollPane().getViewport().getViewPosition(); - double newZoom = zoom * DiagramScene.ZOOM_INCREMENT; - if (newZoom < DiagramScene.ZOOM_MAX_FACTOR) { - setZoomFactor(newZoom); - validate(); - getScrollPane().getViewport().setViewPosition(new Point((int) (viewPosition.x * DiagramScene.ZOOM_INCREMENT), (int) (viewPosition.y * DiagramScene.ZOOM_INCREMENT))); - } - } - - private void centerFigures(Collection
list) { - gotoFigures(list); - } - - private RectangularSelectProvider rectangularSelectProvider = new RectangularSelectProvider() { - - @Override - public void performSelection(Rectangle rectangle) { - if (rectangle.width < 0) { - rectangle.x += rectangle.width; - rectangle.width *= -1; - } - - if (rectangle.height < 0) { - rectangle.y += rectangle.height; - rectangle.height *= -1; - } - - Set selectedObjects = new HashSet<>(); - for (Figure f : getModel().getDiagramToView().getFigures()) { - FigureWidget w = getWidget(f); - if (w != null) { - Rectangle r = new Rectangle(w.getBounds()); - r.setLocation(w.getLocation()); - - if (r.intersects(rectangle)) { - selectedObjects.add(f); - } - - for (Slot s : f.getSlots()) { - SlotWidget sw = getWidget(s); - Rectangle r2 = new Rectangle(sw.getBounds()); - r2.setLocation(sw.convertLocalToScene(new Point(0, 0))); - - if (r2.intersects(rectangle)) { - selectedObjects.add(s); - } - } - } else { - assert false : "w should not be null here!"; - } - } - - setSelectedObjects(selectedObjects); - } - }; - private MouseWheelListener mouseWheelListener = new MouseWheelListener() { - - @Override - public void mouseWheelMoved(MouseWheelEvent e) { - if (e.isControlDown()) { - DiagramScene.this.relayoutWithoutLayout(null); - } - } - }; - - public Point getScrollPosition() { - return getScrollPane().getViewport().getViewPosition(); - } - - public void setScrollPosition(Point p) { - getScrollPane().getViewport().setViewPosition(p); - } - - private JScrollPane createScrollPane() { - JComponent comp = this.createView(); - comp.setDoubleBuffered(true); - comp.setBackground(Color.WHITE); - comp.setOpaque(true); - this.setBackground(Color.WHITE); - this.setOpaque(true); - JScrollPane result = new JScrollPane(comp); - result.setBackground(Color.WHITE); - result.getVerticalScrollBar().setUnitIncrement(SCROLL_UNIT_INCREMENT); - result.getVerticalScrollBar().setBlockIncrement(SCROLL_BLOCK_INCREMENT); - result.getHorizontalScrollBar().setUnitIncrement(SCROLL_UNIT_INCREMENT); - result.getHorizontalScrollBar().setBlockIncrement(SCROLL_BLOCK_INCREMENT); - return result; - } - private ObjectSceneListener selectionChangedListener = new ObjectSceneListener() { - - @Override - public void objectAdded(ObjectSceneEvent arg0, Object arg1) { - } - - @Override - public void objectRemoved(ObjectSceneEvent arg0, Object arg1) { - } - - @Override - public void objectStateChanged(ObjectSceneEvent e, Object o, ObjectState oldState, ObjectState newState) { - } - - @Override - public void selectionChanged(ObjectSceneEvent e, Set oldSet, Set newSet) { - DiagramScene scene = (DiagramScene) e.getObjectScene(); - if (scene.isRebuilding()) { - return; - } - - content.set(newSet, null); - - Set nodeSelection = new HashSet<>(); - for (Object o : newSet) { - if (o instanceof Properties.Provider) { - final Properties.Provider provider = (Properties.Provider) o; - AbstractNode node = new AbstractNode(Children.LEAF) { - - @Override - protected Sheet createSheet() { - Sheet s = super.createSheet(); - PropertiesSheet.initializeSheet(provider.getProperties(), s); - return s; - } - }; - node.setDisplayName(provider.getProperties().get("name")); - content.add(node); - } - - - if (o instanceof Figure) { - nodeSelection.addAll(((Figure) o).getSource().getSourceNodesAsSet()); - } else if (o instanceof Slot) { - nodeSelection.addAll(((Slot) o).getSource().getSourceNodesAsSet()); - } - } - getModel().setSelectedNodes(nodeSelection); - } - - @Override - public void highlightingChanged(ObjectSceneEvent e, Set oldSet, Set newSet) { - Set nodeHighlighting = new HashSet<>(); - for (Object o : newSet) { - if (o instanceof Figure) { - nodeHighlighting.addAll(((Figure) o).getSource().getSourceNodesAsSet()); - } else if (o instanceof Slot) { - nodeHighlighting.addAll(((Slot) o).getSource().getSourceNodesAsSet()); - } - } -// boolean b = highlightedCoordinatorListener.isEnabled(); -// highlightedCoordinatorListener.setEnabled(false); -// SelectionCoordinator.getInstance().setHighlightedObjects(nodeHighlighting); -// highlightedCoordinatorListener.setEnabled(b); - validate(); - } - - @Override - public void hoverChanged(ObjectSceneEvent e, Object oldObject, Object newObject) { - Set newHighlightedObjects = new HashSet<>(DiagramScene.this.getHighlightedObjects()); - if (oldObject != null) { - newHighlightedObjects.remove(oldObject); - } - if (newObject != null) { - newHighlightedObjects.add(newObject); - } - DiagramScene.this.setHighlightedObjects(newHighlightedObjects); - } - - @Override - public void focusChanged(ObjectSceneEvent arg0, Object arg1, Object arg2) { - } - }; - - public void setActions(Action[] actions) { - this.actions = actions; - } - - - - public DiagramScene(DiagramViewModel model) { - - this.model = model; - content = new InstanceContent(); - lookup = new AbstractLookup(content); - content.add(this); - - this.setCheckClipping(true); - - scrollPane = createScrollPane(); - - hoverAction = createObjectHoverAction(); - - // This panAction handles the event only when the left mouse button is - // pressed without any modifier keys, otherwise it will not consume it - // and the selection action (below) will handle the event - panAction = new CustomizablePanWidgetAction(~0, MouseEvent.BUTTON1_DOWN_MASK); - this.getActions().addAction(panAction); - - selectAction = createSelectAction(); - this.getActions().addAction(selectAction); - - blockLayer = new LayerWidget(this); - this.addChild(blockLayer); - - mainLayer = new LayerWidget(this); - this.addChild(mainLayer); - - topLeft = new Widget(this); - topLeft.setPreferredLocation(new Point(-BORDER_SIZE, -BORDER_SIZE)); - this.addChild(topLeft); - - bottomRight = new Widget(this); - bottomRight.setPreferredLocation(new Point(-BORDER_SIZE, -BORDER_SIZE)); - this.addChild(bottomRight); - - connectionLayer = new LayerWidget(this); - this.addChild(connectionLayer); - - LayerWidget selectionLayer = new LayerWidget(this); - this.addChild(selectionLayer); - - this.setLayout(LayoutFactory.createAbsoluteLayout()); - - this.getInputBindings().setZoomActionModifiers(KeyEvent.CTRL_MASK); - zoomAction = ActionFactory.createMouseCenteredZoomAction(1.2); - this.getActions().addAction(zoomAction); - this.getView().addMouseWheelListener(mouseWheelListener); - this.getActions().addAction(ActionFactory.createPopupMenuAction(popupMenuProvider)); - - this.getActions().addAction(ActionFactory.createWheelPanAction()); - - LayerWidget selectLayer = new LayerWidget(this); - this.addChild(selectLayer); - this.getActions().addAction(ActionFactory.createRectangularSelectAction(rectangularSelectDecorator, selectLayer, rectangularSelectProvider)); - - this.addObjectSceneListener(selectionChangedListener, ObjectSceneEventType.OBJECT_SELECTION_CHANGED, ObjectSceneEventType.OBJECT_HIGHLIGHTING_CHANGED, ObjectSceneEventType.OBJECT_HOVER_CHANGED); - - update(); - } - - public DiagramViewModel getModel() { - return model; - } - - public JScrollPane getScrollPane() { - return scrollPane; - } - - Component getComponent() { - return scrollPane; - } - - public boolean isAllVisible() { - return getModel().getHiddenNodes().isEmpty(); - } - - public Action createGotoAction(final Figure f) { - final DiagramScene diagramScene = this; - Action a = new AbstractAction() { - - @Override - public void actionPerformed(ActionEvent e) { - diagramScene.gotoFigure(f); - } - }; - - a.setEnabled(true); - a.putValue(Action.SMALL_ICON, new ColorIcon(f.getColor())); - String name = f.getLines()[0]; - - name += " ("; - - if (!this.getWidget(f, FigureWidget.class).isVisible()) { - name += "hidden"; - } - name += ")"; - a.putValue(Action.NAME, name); - return a; - } - - private void update() { - mainLayer.removeChildren(); - blockLayer.removeChildren(); - - rebuilding = true; - - Collection objects = new ArrayList<>(this.getObjects()); - for (Object o : objects) { - this.removeObject(o); - } - - Diagram d = getModel().getDiagramToView(); - - for (Figure f : d.getFigures()) { - FigureWidget w = new FigureWidget(f, hoverAction, selectAction, this, mainLayer); - w.getActions().addAction(ActionFactory.createPopupMenuAction(w)); - w.getActions().addAction(selectAction); - w.getActions().addAction(hoverAction); - w.setVisible(false); - - this.addObject(f, w); - - for (InputSlot s : f.getInputSlots()) { - SlotWidget sw = new InputSlotWidget(s, this, w, w); - addObject(s, sw); - sw.getActions().addAction(new DoubleClickAction(sw)); - sw.getActions().addAction(hoverAction); - sw.getActions().addAction(selectAction); - } - - for (OutputSlot s : f.getOutputSlots()) { - SlotWidget sw = new OutputSlotWidget(s, this, w, w); - addObject(s, sw); - sw.getActions().addAction(new DoubleClickAction(sw)); - sw.getActions().addAction(hoverAction); - sw.getActions().addAction(selectAction); - } - } - - rebuilding = false; - this.smallUpdate(true); - } - - public boolean isRebuilding() { - return rebuilding; - } - - private void smallUpdate(boolean relayout) { - - this.updateHiddenNodes(model.getHiddenNodes(), relayout); - this.validate(); - } - - private boolean isVisible(Connection c) { - FigureWidget w1 = getWidget(c.getInputSlot().getFigure()); - FigureWidget w2 = getWidget(c.getOutputSlot().getFigure()); - - if (w1.isVisible() && w2.isVisible()) { - return true; - } - - return false; - } - - private void relayout(Set oldVisibleWidgets) { - System.out.println("relayout called with old visible widgets: " + oldVisibleWidgets); - - Diagram diagram = getModel().getDiagramToView(); - - HashSet
figures = new HashSet<>(); - - for (Figure f : diagram.getFigures()) { - FigureWidget w = getWidget(f); - if (w.isVisible()) { - figures.add(f); - } - } - - HashSet edges = new HashSet<>(); - - for (Connection c : diagram.getConnections()) { - if (isVisible(c)) { - edges.add(c); - } - } - - HierarchicalLayoutManager manager = new HierarchicalLayoutManager(HierarchicalLayoutManager.Combine.SAME_OUTPUTS); - manager.setMaxLayerLength(10); - manager.doLayout(new LayoutGraph(edges, figures)); - relayoutWithoutLayout(oldVisibleWidgets); - } - private Set> lineCache = new HashSet<>(); - - private void relayoutWithoutLayout(Set oldVisibleWidgets) { - - System.out.println("relayout without layout with visible widgets: " + oldVisibleWidgets); - - Diagram diagram = getModel().getDiagramToView(); - - int maxX = -BORDER_SIZE; - int maxY = -BORDER_SIZE; - for (Figure f : diagram.getFigures()) { - FigureWidget w = getWidget(f); - if (w.isVisible()) { - Point p = f.getPosition(); - Dimension d = f.getSize(); - maxX = Math.max(maxX, p.x + d.width); - maxY = Math.max(maxY, p.y + d.height); - } - } - - for (Connection c : diagram.getConnections()) { - List points = c.getControlPoints(); - FigureWidget w1 = getWidget((Figure) c.getTo().getVertex()); - FigureWidget w2 = getWidget((Figure) c.getFrom().getVertex()); - if (w1.isVisible() && w2.isVisible()) { - for (Point p : points) { - if (p != null) { - maxX = Math.max(maxX, p.x); - maxY = Math.max(maxY, p.y); - } - } - } - } - - bottomRight.setPreferredLocation(new Point(maxX + BORDER_SIZE, maxY + BORDER_SIZE)); - int offx = 0; - int offy = 0; - int curWidth = maxX + 2 * BORDER_SIZE; - int curHeight = maxY + 2 * BORDER_SIZE; - - Rectangle bounds = this.getScrollPane().getBounds(); - bounds.width /= getZoomFactor(); - bounds.height /= getZoomFactor(); - if (curWidth < bounds.width) { - offx = (bounds.width - curWidth) / 2; - } - - if (curHeight < bounds.height) { - offy = (bounds.height - curHeight) / 2; - } - - final int offx2 = offx; - final int offy2 = offy; - - SceneAnimator animator = this.getSceneAnimator(); - connectionLayer.removeChildren(); - int visibleFigureCount = 0; - for (Figure f : diagram.getFigures()) { - if (getWidget(f, FigureWidget.class).isVisible()) { - visibleFigureCount++; - } - } - - - Set> lastLineCache = lineCache; - lineCache = new HashSet<>(); - for (Figure f : diagram.getFigures()) { - for (OutputSlot s : f.getOutputSlots()) { - SceneAnimator anim = animator; - if (visibleFigureCount > ANIMATION_LIMIT || oldVisibleWidgets == null) { - anim = null; - } - processOutputSlot(lastLineCache, s, s.getConnections(), 0, null, null, offx2, offy2, anim); - } - } - - for (Figure f : diagram.getFigures()) { - FigureWidget w = getWidget(f); - if (w.isVisible()) { - Point p = f.getPosition(); - Point p2 = new Point(p.x + offx2, p.y + offy2); - if ((visibleFigureCount <= ANIMATION_LIMIT && oldVisibleWidgets != null && oldVisibleWidgets.contains(w))) { - animator.animatePreferredLocation(w, p2); - } else { - w.setPreferredLocation(p2); - animator.animatePreferredLocation(w, p2); - } - } - } - - this.validate(); - } - private final Point specialNullPoint = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE); - - private void processOutputSlot(Set> lastLineCache, OutputSlot s, List connections, int controlPointIndex, Point lastPoint, LineWidget predecessor, int offx, int offy, SceneAnimator animator) { - Map> pointMap = new HashMap<>(connections.size()); - - for (Connection c : connections) { - - if (!isVisible(c)) { - continue; - } - - List controlPoints = c.getControlPoints(); - if (controlPointIndex >= controlPoints.size()) { - continue; - } - - Point cur = controlPoints.get(controlPointIndex); - if (cur == null) { - cur = specialNullPoint; - } else if (controlPointIndex == 0 && !s.shouldShowName()) { - cur = new Point(cur.x, cur.y - SLOT_OFFSET); - } else if (controlPointIndex == controlPoints.size() - 1 && !c.getInputSlot().shouldShowName()) { - cur = new Point(cur.x, cur.y + SLOT_OFFSET); - } - - if (pointMap.containsKey(cur)) { - pointMap.get(cur).add(c); - } else { - List newList = new ArrayList<>(2); - newList.add(c); - pointMap.put(cur, newList); - } - - } - - for (Point p : pointMap.keySet()) { - List connectionList = pointMap.get(p); - - boolean isBold = false; - boolean isDashed = true; - - for (Connection c : connectionList) { - - if (c.getStyle() == Connection.ConnectionStyle.BOLD) { - isBold = true; - } - - if (c.getStyle() != Connection.ConnectionStyle.DASHED) { - isDashed = false; - } - } - - LineWidget newPredecessor = predecessor; - if (p == specialNullPoint) { - } else if (lastPoint == specialNullPoint) { - } else if (lastPoint != null) { - Point p1 = new Point(lastPoint.x + offx, lastPoint.y + offy); - Point p2 = new Point(p.x + offx, p.y + offy); - - Pair curPair = new Pair<>(p1, p2); - SceneAnimator curAnimator = animator; - if (lastLineCache.contains(curPair)) { - curAnimator = null; - } - LineWidget w = new LineWidget(this, s, connectionList, p1, p2, predecessor, curAnimator, isBold, isDashed); - lineCache.add(curPair); - - newPredecessor = w; - connectionLayer.addChild(w); - w.getActions().addAction(hoverAction); - } - - processOutputSlot(lastLineCache, s, connectionList, controlPointIndex + 1, p, newPredecessor, offx, offy, animator); - } - } - - @Override - public Lookup getLookup() { - return lookup; - } - - private void gotoFigures(final Collection
figures) { - Rectangle overall = null; - getModel().showFigures(figures); - for (Figure f : figures) { - - FigureWidget fw = getWidget(f); - if (fw != null) { - Rectangle r = fw.getBounds(); - Point p = fw.getLocation(); - Rectangle r2 = new Rectangle(p.x, p.y, r.width, r.height); - - if (overall == null) { - overall = r2; - } else { - overall = overall.union(r2); - } - } - } - if (overall != null) { - centerRectangle(overall); - } - } - - private Set idSetToObjectSet(Set ids) { - - Set result = new HashSet<>(); - for (Figure f : getModel().getDiagramToView().getFigures()) { - if (DiagramScene.doesIntersect(f.getSource().getSourceNodesAsSet(), ids)) { - result.add(f); - } - - for (Slot s : f.getSlots()) { - if (DiagramScene.doesIntersect(s.getSource().getSourceNodesAsSet(), ids)) { - result.add(s); - } - } - } - return result; - } - - public void gotoSelection(Set ids) { - - Rectangle overall = null; - Set hiddenNodes = new HashSet<>(this.getModel().getHiddenNodes()); - hiddenNodes.removeAll(ids); - this.getModel().showNot(hiddenNodes); - - Set objects = idSetToObjectSet(ids); - for (Object o : objects) { - - Widget w = getWidget(o); - if (w != null) { - Rectangle r = w.getBounds(); - Point p = w.convertLocalToScene(new Point(0, 0)); - - Rectangle r2 = new Rectangle(p.x, p.y, r.width, r.height); - - if (overall == null) { - overall = r2; - } else { - overall = overall.union(r2); - } - } - } - if (overall != null) { - centerRectangle(overall); - } - - setSelectedObjects(objects); - } - - private Point calcCenter(Rectangle r) { - - Point center = new Point((int) r.getCenterX(), (int) r.getCenterY()); - center.x -= getScrollPane().getViewport().getViewRect().width / 2; - center.y -= getScrollPane().getViewport().getViewRect().height / 2; - - // Ensure to be within area - center.x = Math.max(0, center.x); - center.x = Math.min(getScrollPane().getViewport().getViewSize().width - getScrollPane().getViewport().getViewRect().width, center.x); - center.y = Math.max(0, center.y); - center.y = Math.min(getScrollPane().getViewport().getViewSize().height - getScrollPane().getViewport().getViewRect().height, center.y); - - return center; - } - - private void centerRectangle(Rectangle r) { - - if (getScrollPane().getViewport().getViewRect().width == 0 || getScrollPane().getViewport().getViewRect().height == 0) { - return; - } - - Rectangle r2 = new Rectangle(r.x, r.y, r.width, r.height); - r2 = convertSceneToView(r2); - - double factorX = (double) r2.width / (double) getScrollPane().getViewport().getViewRect().width; - double factorY = (double) r2.height / (double) getScrollPane().getViewport().getViewRect().height; - double factor = Math.max(factorX, factorY); - if (factor >= 1.0) { - Point p = getScrollPane().getViewport().getViewPosition(); - setZoomFactor(getZoomFactor() / factor); - r2.x /= factor; - r2.y /= factor; - r2.width /= factor; - r2.height /= factor; - getScrollPane().getViewport().setViewPosition(calcCenter(r2)); - } else { - getScrollPane().getViewport().setViewPosition(calcCenter(r2)); - } - } - - void setSelection(Collection
list) { - super.setSelectedObjects(new HashSet<>(list)); - centerFigures(list); - } - - private boolean isVisible(Figure f) { - for (Integer n : f.getSource().getSourceNodesAsSet()) { - if (getModel().getHiddenNodes().contains(n)) { - return false; - } - } - return true; - } - - public static boolean doesIntersect(Set s1, Set s2) { - if (s1.size() > s2.size()) { - Set tmp = s1; - s1 = s2; - s2 = tmp; - } - - for (Object o : s1) { - if (s2.contains(o)) { - return true; - } - } - - return false; - } - - private void updateHiddenNodes(Set newHiddenNodes, boolean doRelayout) { - - System.out.println("newHiddenNodes: " + newHiddenNodes); - - Diagram diagram = getModel().getDiagramToView(); - assert diagram != null; - - Set oldVisibleWidgets = new HashSet<>(); - - for (Figure f : diagram.getFigures()) { - FigureWidget w = getWidget(f); - if (w != null && w.isVisible()) { - oldVisibleWidgets.add(w); - } - } - - for (Figure f : diagram.getFigures()) { - boolean hiddenAfter = doesIntersect(f.getSource().getSourceNodesAsSet(), newHiddenNodes); - - FigureWidget w = getWidget(f); - w.setBoundary(false); - if (!hiddenAfter) { - // Figure is shown - w.setVisible(true); - } else { - // Figure is hidden - w.setVisible(false); - } - } - - if (getModel().getShowNodeHull()) { - List boundaries = new ArrayList<>(); - for (Figure f : diagram.getFigures()) { - FigureWidget w = getWidget(f); - if (!w.isVisible()) { - Set
set = new HashSet<>(f.getPredecessorSet()); - set.addAll(f.getSuccessorSet()); - - boolean b = false; - for (Figure neighbor : set) { - FigureWidget neighborWidget = getWidget(neighbor); - if (neighborWidget.isVisible()) { - b = true; - break; - } - } - - if (b) { - w.setBoundary(true); - boundaries.add(w); - } - } - } - - for (FigureWidget w : boundaries) { - if (w.isBoundary()) { - w.setVisible(true); - } - } - } - - if (doRelayout) { - relayout(oldVisibleWidgets); - } - this.validate(); - } - - private void showFigure(Figure f) { - HashSet newHiddenNodes = new HashSet<>(getModel().getHiddenNodes()); - newHiddenNodes.removeAll(f.getSource().getSourceNodesAsSet()); - updateHiddenNodes(newHiddenNodes, true); - } - - public void show(final Figure f) { - showFigure(f); - } - - public void setSelectedObjects(Object... args) { - Set set = new HashSet<>(); - for (Object o : args) { - set.add(o); - } - super.setSelectedObjects(set); - } - - private void centerWidget(Widget w) { - Rectangle r = w.getBounds(); - Point p = w.getLocation(); - centerRectangle(new Rectangle(p.x, p.y, r.width, r.height)); - } - - public void gotoFigure(final Figure f) { - if (!isVisible(f)) { - showFigure(f); - } - - FigureWidget fw = getWidget(f); - if (fw != null) { - setSelection(new HashSet<>(Arrays.asList(f))); - } - } - - public JPopupMenu createPopupMenu() { - JPopupMenu menu = new JPopupMenu(); - for (Action a : actions) { - if (a == null) { - menu.addSeparator(); - } else { - menu.add(a); - } - } - return menu; - } - - private final ChangedListener fullChange = new ChangedListener() { - - @Override - public void changed(DiagramViewModel source) { - assert source == model : "Receive only changed event from current model!"; - assert source != null; - update(); - } - }; - private final ChangedListener hiddenNodesChange = new ChangedListener() { - - @Override - public void changed(DiagramViewModel source) { - assert source == model : "Receive only changed event from current model!"; - assert source != null; - smallUpdate(true); - } - }; - private final ChangedListener selectionChange = new ChangedListener() { - - @Override - public void changed(DiagramViewModel source) { - assert source == model : "Receive only changed event from current model!"; - assert source != null; - smallUpdate(false); - } - }; - - @Override - public void showAll() { - // TODO(tw): Implement. - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/scene/GraphCompilationViewer.java --- a/visualizer/View/src/com/sun/hotspot/igv/view/scene/GraphCompilationViewer.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.sun.hotspot.igv.view.scene; - -import com.sun.hotspot.igv.svg.BatikSVG; -import com.oracle.graal.visualizer.editor.CompilationViewer; -import com.oracle.graal.visualizer.editor.DiagramViewModel; -import com.sun.hotspot.igv.graph.Figure; -import com.sun.hotspot.igv.view.actions.*; -import java.awt.Component; -import java.awt.Graphics2D; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.*; -import java.util.Collection; -import javax.swing.Action; -import javax.swing.JToggleButton; -import javax.swing.JToolBar; -import org.openide.DialogDisplayer; -import org.openide.NotifyDescriptor; -import org.openide.util.Lookup; -import org.openide.util.lookup.Lookups; -import org.openide.util.lookup.ProxyLookup; - -public class GraphCompilationViewer implements CompilationViewer, PropertyChangeListener { - - private DiagramScene scene; - private PredSuccAction predSuccAction; - - GraphCompilationViewer(DiagramViewModel model) { - - scene = new DiagramScene(model); - - Action[] actions = new Action[]{ - }; - - scene.setActions(actions); - } - - @Override - public Lookup getLookup() { - return scene.getLookup(); - } - - @Override - public Component getComponent() { - return scene.getComponent(); - } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (evt.getSource() == this.predSuccAction) { - boolean b = (Boolean) predSuccAction.getValue(PredSuccAction.STATE); - scene.getModel().setShowNodeHull(b); - } else { - assert false : "Unknown event source"; - } - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/scene/GraphCompilationViewerFactory.java --- a/visualizer/View/src/com/sun/hotspot/igv/view/scene/GraphCompilationViewerFactory.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package com.sun.hotspot.igv.view.scene; - -import com.oracle.graal.visualizer.editor.CompilationViewer; -import com.oracle.graal.visualizer.editor.CompilationViewerFactory; -import com.oracle.graal.visualizer.editor.DiagramViewModel; -import com.sun.hotspot.igv.data.InputGraph; -import com.sun.hotspot.igv.filter.FilterChain; -import com.sun.hotspot.igv.filter.FilterChainProvider; -import org.openide.util.Lookup; - -public class GraphCompilationViewerFactory implements CompilationViewerFactory{ - - @Override - public CompilationViewer createViewer(InputGraph firstGraph, InputGraph secondGraph) { - FilterChain filterChain; - FilterChain sequence; - FilterChainProvider provider = Lookup.getDefault().lookup(FilterChainProvider.class); - if (provider == null) { - filterChain = new FilterChain(); - sequence = new FilterChain(); - } else { - filterChain = provider.getFilterChain(); - sequence = provider.getSequence(); - } - DiagramViewModel model = new DiagramViewModel(firstGraph, secondGraph, firstGraph.getGroup(), filterChain, filterChain); - return new GraphCompilationViewer(model); - } - - @Override - public String getName() { - return "Graph"; - } - -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/widgets/FigureWidget.java --- a/visualizer/View/src/com/sun/hotspot/igv/view/widgets/FigureWidget.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,363 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.view.widgets; - -import com.sun.hotspot.igv.data.Properties; -import com.sun.hotspot.igv.graph.Figure; -import com.sun.hotspot.igv.util.DoubleClickAction; -import com.sun.hotspot.igv.util.DoubleClickHandler; -import com.sun.hotspot.igv.util.PropertiesSheet; -import com.sun.hotspot.igv.view.scene.DiagramScene; -import java.awt.*; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Set; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.JMenu; -import javax.swing.JPopupMenu; -import javax.swing.event.MenuEvent; -import javax.swing.event.MenuListener; -import org.netbeans.api.visual.action.PopupMenuProvider; -import org.netbeans.api.visual.action.WidgetAction; -import org.netbeans.api.visual.layout.LayoutFactory; -import org.netbeans.api.visual.model.ObjectState; -import org.netbeans.api.visual.widget.LabelWidget; -import org.netbeans.api.visual.widget.Widget; -import org.openide.nodes.AbstractNode; -import org.openide.nodes.Children; -import org.openide.nodes.Node; -import org.openide.nodes.Sheet; - -/** - * - * @author Thomas Wuerthinger - */ -public class FigureWidget extends Widget implements Properties.Provider, PopupMenuProvider, DoubleClickHandler { - - public static final boolean VERTICAL_LAYOUT = true; - //public static final int MAX_STRING_LENGTH = 20; - private static final double LABEL_ZOOM_FACTOR = 0.3; - private static final double ZOOM_FACTOR = 0.1; - private Font font; - private Font boldFont; - private Figure figure; - private Widget leftWidget; - private Widget rightWidget; - private Widget middleWidget; - private ArrayList labelWidgets; - private DiagramScene diagramScene; - private boolean boundary; - private Node node; - private Widget dummyTop; - - public void setBoundary(boolean b) { - boundary = b; - } - - public boolean isBoundary() { - return boundary; - } - - public Node getNode() { - return node; - } - - @Override - public boolean isHitAt(Point localLocation) { - return middleWidget.isHitAt(localLocation); - } - - - public FigureWidget(final Figure f, WidgetAction hoverAction, WidgetAction selectAction, DiagramScene scene, Widget parent) { - - super(scene); - - assert this.getScene() != null; - assert this.getScene().getView() != null; - - this.figure = f; - font = f.getDiagram().getFont(); - boldFont = f.getDiagram().getFont().deriveFont(Font.BOLD); - this.setCheckClipping(true); - this.diagramScene = scene; - parent.addChild(this); - - Widget outer = new Widget(scene); - outer.setBackground(f.getColor()); - outer.setLayout(LayoutFactory.createOverlayLayout()); - - middleWidget = new Widget(scene); - middleWidget.setLayout(LayoutFactory.createVerticalFlowLayout(LayoutFactory.SerialAlignment.CENTER, 0)); - middleWidget.setBackground(f.getColor()); - middleWidget.setOpaque(true); - //middleWidget.setBorder(BorderFactory.createLineBorder(Color.BLACK)); - middleWidget.getActions().addAction(new DoubleClickAction(this)); - middleWidget.setCheckClipping(true); - - labelWidgets = new ArrayList<>(); - - String[] strings = figure.getLines(); - - dummyTop = new Widget(scene); - dummyTop.setMinimumSize(new Dimension(Figure.INSET / 2, 1)); - middleWidget.addChild(dummyTop); - - - for (String cur : strings) { - - String displayString = cur; - - LabelWidget lw = new LabelWidget(scene); - labelWidgets.add(lw); - middleWidget.addChild(lw); - lw.setLabel(displayString); - lw.setFont(font); - lw.setForeground(Color.BLACK); - lw.setAlignment(LabelWidget.Alignment.CENTER); - lw.setVerticalAlignment(LabelWidget.VerticalAlignment.CENTER); - lw.setBorder(BorderFactory.createEmptyBorder()); - } - - Widget dummyBottom = new Widget(scene); - dummyBottom.setMinimumSize(new Dimension(Figure.INSET / 2, 1)); - middleWidget.addChild(dummyBottom); - - middleWidget.setPreferredBounds(new Rectangle(0, Figure.SLOT_WIDTH - Figure.OVERLAPPING, f.getWidth(), f.getHeight())); - //outer.addChild(middleWidget); - this.addChild(middleWidget); - - // Initialize node for property sheet - node = new AbstractNode(Children.LEAF) { - - @Override - protected Sheet createSheet() { - Sheet s = super.createSheet(); - PropertiesSheet.initializeSheet(f.getProperties(), s); - return s; - } - }; - node.setDisplayName(getName()); - } - - public Widget getLeftWidget() { - return leftWidget; - } - - public Widget getRightWidget() { - return rightWidget; - } - - @Override - protected void notifyStateChanged(ObjectState previousState, ObjectState state) { - super.notifyStateChanged(previousState, state); - - Color borderColor = Color.BLACK; - Color innerBorderColor = getFigure().getColor(); - int thickness = 1; - boolean repaint = false; - Font f = font; - if (state.isSelected() || state.isHighlighted()) { - thickness = 2; - } - if(state.isSelected()) { - f = boldFont; - innerBorderColor = borderColor; - } else { - } - - if (state.isHighlighted()) { - innerBorderColor = borderColor = Color.BLUE; - repaint = true; - } else { - repaint = true; - } - - if (state.isHovered() != previousState.isHovered()) { - - /* - if (state.isHovered()) { - diagramScene.addAllHighlighted(this.getFigure().getSource().getSourceNodesAsSet()); - } else { - diagramScene.removeAllHighlighted(this.getFigure().getSource().getSourceNodesAsSet()); - }*/ - repaint = true; - } - - if (state.isSelected() != previousState.isSelected()) { - repaint = true; - } - - if (repaint) { - middleWidget.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(borderColor, 1), BorderFactory.createLineBorder(innerBorderColor, 1))); - for (LabelWidget labelWidget : labelWidgets) { - labelWidget.setFont(f); - } - repaint(); - } - } - - public String getName() { - return getProperties().get("name"); - } - - @Override - public Properties getProperties() { - return figure.getProperties(); - } - - public Figure getFigure() { - return figure; - } - - @Override - protected void paintChildren() { - Composite oldComposite = null; - if (boundary) { - oldComposite = getScene().getGraphics().getComposite(); - float alpha = DiagramScene.ALPHA; - this.getScene().getGraphics().setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha)); - } - - if (diagramScene.getZoomFactor() < LABEL_ZOOM_FACTOR) { - - for (LabelWidget labelWidget : labelWidgets) { - labelWidget.setVisible(false); - } - super.paintChildren(); - for (LabelWidget labelWidget : labelWidgets) { - labelWidget.setVisible(true); - } - - } else { - super.paintChildren(); - } - - if (boundary) { - getScene().getGraphics().setComposite(oldComposite); - } - } - - @Override - public JPopupMenu getPopupMenu(Widget widget, Point point) { - JPopupMenu menu = diagramScene.createPopupMenu(); - menu.addSeparator(); - - JMenu predecessors = new JMenu("Nodes Above"); - predecessors.addMenuListener(new NeighborMenuListener(predecessors, getFigure(), false)); - menu.add(predecessors); - - JMenu successors = new JMenu("Nodes Below"); - successors.addMenuListener(new NeighborMenuListener(successors, getFigure(), true)); - menu.add(successors); - - return menu; - } - - /** - * Builds the submenu for a figure's neighbors on demand. - */ - private class NeighborMenuListener implements MenuListener { - - private final JMenu menu; - private final Figure figure; - private final boolean successors; - - public NeighborMenuListener(JMenu menu, Figure figure, boolean successors) { - this.menu = menu; - this.figure = figure; - this.successors = successors; - } - - @Override - public void menuSelected(MenuEvent e) { - if (menu.getItemCount() > 0) { - // already built before - return; - } - - Set
set = figure.getPredecessorSet(); - if (successors) { - set = figure.getSuccessorSet(); - } - - boolean first = true; - for (Figure f : set) { - if (f == figure) { - continue; - } - - if (first) { - first = false; - } else { - menu.addSeparator(); - } - - Action go = diagramScene.createGotoAction(f); - menu.add(go); - - JMenu preds = new JMenu("Nodes Above"); - preds.addMenuListener(new NeighborMenuListener(preds, f, false)); - menu.add(preds); - - JMenu succs = new JMenu("Nodes Below"); - succs.addMenuListener(new NeighborMenuListener(succs, f, true)); - menu.add(succs); - } - - if (menu.getItemCount() == 0) { - menu.add("(none)"); - } - } - - @Override - public void menuDeselected(MenuEvent e) { - // ignore - } - - @Override - public void menuCanceled(MenuEvent e) { - // ignore - } - } - - @Override - public void handleDoubleClick(Widget w, WidgetAction.WidgetMouseEvent e) { - - if (diagramScene.isAllVisible()) { - final Set hiddenNodes = new HashSet<>(diagramScene.getModel().getGraphToView().getGroup().getAllNodes()); - hiddenNodes.removeAll(this.getFigure().getSource().getSourceNodesAsSet()); - this.diagramScene.getModel().showNot(hiddenNodes); - } else if (isBoundary()) { - - final Set hiddenNodes = new HashSet<>(diagramScene.getModel().getHiddenNodes()); - hiddenNodes.removeAll(this.getFigure().getSource().getSourceNodesAsSet()); - this.diagramScene.getModel().showNot(hiddenNodes); - } else { - final Set hiddenNodes = new HashSet<>(diagramScene.getModel().getHiddenNodes()); - hiddenNodes.addAll(this.getFigure().getSource().getSourceNodesAsSet()); - this.diagramScene.getModel().showNot(hiddenNodes); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/widgets/InputSlotWidget.java --- a/visualizer/View/src/com/sun/hotspot/igv/view/widgets/InputSlotWidget.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.view.widgets; - -import com.sun.hotspot.igv.graph.Figure; -import com.sun.hotspot.igv.graph.InputSlot; -import com.sun.hotspot.igv.view.scene.DiagramScene; -import java.awt.Point; -import java.util.List; -import org.netbeans.api.visual.widget.Widget; - -/** - * - * @author Thomas Wuerthinger - */ -public class InputSlotWidget extends SlotWidget { - - private InputSlot inputSlot; - - public InputSlotWidget(InputSlot slot, DiagramScene scene, Widget parent, FigureWidget fw) { - super(slot, scene, parent, fw); - inputSlot = slot; - //init(); - //getFigureWidget().getLeftWidget().addChild(this); - Point p = inputSlot.getRelativePosition(); - p.x -= this.calculateClientArea().width / 2; - p.y += Figure.SLOT_START; - this.setPreferredLocation(p); - } - - public InputSlot getInputSlot() { - return inputSlot; - } - - @Override - protected int calculateSlotWidth() { - List slots = getSlot().getFigure().getInputSlots(); - assert slots.contains(getSlot()); - return calculateWidth(slots.size()); - } -/* - protected Point calculateRelativeLocation() { - if (getFigureWidget().getBounds() == null) { - return new Point(0, 0); - } - - double x = 0; - List slots = inputSlot.getFigure().getInputSlots(); - assert slots.contains(inputSlot); - return new Point((int) x, (int) (calculateRelativeY(slots.size(), slots.indexOf(inputSlot)))); - }*/ -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/widgets/LineWidget.java --- a/visualizer/View/src/com/sun/hotspot/igv/view/widgets/LineWidget.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,343 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.view.widgets; - -import com.sun.hotspot.igv.graph.Connection; -import com.sun.hotspot.igv.graph.Figure; -import com.sun.hotspot.igv.graph.InputSlot; -import com.sun.hotspot.igv.graph.OutputSlot; -import com.sun.hotspot.igv.view.scene.DiagramScene; -import java.awt.*; -import java.awt.geom.Line2D; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import javax.swing.JPopupMenu; -import javax.swing.event.PopupMenuEvent; -import javax.swing.event.PopupMenuListener; -import org.netbeans.api.visual.action.ActionFactory; -import org.netbeans.api.visual.action.PopupMenuProvider; -import org.netbeans.api.visual.action.SelectProvider; -import org.netbeans.api.visual.animator.SceneAnimator; -import org.netbeans.api.visual.model.ObjectState; -import org.netbeans.api.visual.widget.Widget; - -/** - * - * @author Thomas Wuerthinger - */ -public class LineWidget extends Widget implements PopupMenuProvider { - - public final int BORDER = 5; - public final int ARROW_SIZE = 6; - public final int BOLD_ARROW_SIZE = 7; - public final int HOVER_ARROW_SIZE = 8; - public final int BOLD_STROKE_WIDTH = 2; - public final int HOVER_STROKE_WIDTH = 3; - private static double ZOOM_FACTOR = 0.1; - private OutputSlot outputSlot; - private DiagramScene scene; - private List connections; - private Point from; - private Point to; - private Rectangle clientArea; - private Color color = Color.BLACK; - private LineWidget predecessor; - private List successors; - private boolean highlighted; - private boolean popupVisible; - private boolean isBold; - private boolean isDashed; - - public LineWidget(DiagramScene scene, OutputSlot s, List connections, Point from, Point to, LineWidget predecessor, SceneAnimator animator, boolean isBold, boolean isDashed) { - super(scene); - this.scene = scene; - this.outputSlot = s; - this.connections = connections; - this.from = from; - this.to = to; - this.predecessor = predecessor; - this.successors = new ArrayList<>(); - if (predecessor != null) { - predecessor.addSuccessor(this); - } - - this.isBold = isBold; - this.isDashed = isDashed; - - int minX = from.x; - int minY = from.y; - int maxX = to.x; - int maxY = to.y; - if (minX > maxX) { - int tmp = minX; - minX = maxX; - maxX = tmp; - } - - if (minY > maxY) { - int tmp = minY; - minY = maxY; - maxY = tmp; - } - - clientArea = new Rectangle(minX, minY, maxX - minX + 1, maxY - minY + 1); - clientArea.grow(BORDER, BORDER); - - if (connections.size() > 0) { - color = connections.get(0).getColor(); - } - - this.setToolTipText("" + generateToolTipText(this.connections) + ""); - - this.setCheckClipping(true); - - this.getActions().addAction(ActionFactory.createPopupMenuAction(this)); - if (animator == null) { - this.setBackground(color); - } else { - this.setBackground(Color.WHITE); - animator.animateBackgroundColor(this, color); - } - - this.getActions().addAction(ActionFactory.createSelectAction(new SelectProvider() { - - @Override - public boolean isAimingAllowed(Widget arg0, Point arg1, boolean arg2) { - return true; - } - - @Override - public boolean isSelectionAllowed(Widget arg0, Point arg1, boolean arg2) { - return true; - } - - @Override - public void select(Widget arg0, Point arg1, boolean arg2) { - Set
set = new HashSet<>(); - for (Connection c : LineWidget.this.connections) { - set.add(c.getInputSlot().getFigure()); - set.add(c.getOutputSlot().getFigure()); - } - LineWidget.this.scene.setSelectedObjects(set); - } - })); - } - - private String generateToolTipText(List conn) { - StringBuilder sb = new StringBuilder(); - for (Connection c : conn) { - sb.append(c.getToolTipText()); - sb.append("
"); - } - return sb.toString(); - } - - public Point getFrom() { - return from; - } - - public Point getTo() { - return to; - } - - private void addSuccessor(LineWidget widget) { - this.successors.add(widget); - } - - @Override - protected Rectangle calculateClientArea() { - return clientArea; - } - - @Override - protected void paintWidget() { - if (scene.getZoomFactor() < ZOOM_FACTOR) { - return; - } - - Graphics2D g = getScene().getGraphics(); - g.setPaint(this.getBackground()); - float width = 1.0f; - - if (isBold) { - width = BOLD_STROKE_WIDTH; - } - - if (highlighted || popupVisible) { - width = HOVER_STROKE_WIDTH; - } - - Stroke oldStroke = g.getStroke(); - if (isDashed) { - float[] dashPattern = {5, 5, 5, 5}; - g.setStroke(new BasicStroke(width, BasicStroke.CAP_BUTT, - BasicStroke.JOIN_MITER, 10, - dashPattern, 0)); - } else { - g.setStroke(new BasicStroke(width)); - } - - g.drawLine(from.x, from.y, to.x, to.y); - - boolean sameFrom = false; - boolean sameTo = successors.size() == 0; - for (LineWidget w : successors) { - if (w.getFrom().equals(getTo())) { - sameTo = true; - } - } - - if (predecessor == null || predecessor.getTo().equals(getFrom())) { - sameFrom = true; - } - - - int size = ARROW_SIZE; - if (isBold) { - size = BOLD_ARROW_SIZE; - } - if (highlighted || popupVisible) { - size = HOVER_ARROW_SIZE; - } - if (!sameFrom) { - g.fillPolygon( - new int[]{from.x - size / 2, from.x + size / 2, from.x}, - new int[]{from.y - size / 2, from.y - size / 2, from.y + size / 2}, - 3); - } - if (!sameTo) { - g.fillPolygon( - new int[]{to.x - size / 2, to.x + size / 2, to.x}, - new int[]{to.y - size / 2, to.y - size / 2, to.y + size / 2}, - 3); - } - g.setStroke(oldStroke); - } - - private void setHighlighted(boolean b) { - this.highlighted = b; - Set highlightedObjects = new HashSet<>(scene.getHighlightedObjects()); - Set highlightedObjectsChange = new HashSet<>(); - for (Connection c : connections) { - highlightedObjectsChange.add(c.getInputSlot().getFigure()); - highlightedObjectsChange.add(c.getInputSlot()); - highlightedObjectsChange.add(c.getOutputSlot().getFigure()); - highlightedObjectsChange.add(c.getOutputSlot()); - } - if(b) { - highlightedObjects.addAll(highlightedObjectsChange); - } else { - highlightedObjects.removeAll(highlightedObjectsChange); - } - scene.setHighlightedObjects(highlightedObjects); - this.revalidate(true); - } - - private void setPopupVisible(boolean b) { - this.popupVisible = b; - this.revalidate(true); - } - - @Override - public boolean isHitAt(Point localPoint) { - return Line2D.ptLineDistSq(from.x, from.y, to.x, to.y, localPoint.x, localPoint.y) <= BORDER * BORDER; - } - - @Override - protected void notifyStateChanged(ObjectState previousState, ObjectState state) { - if (previousState.isHovered() != state.isHovered()) { - setRecursiveHighlighted(state.isHovered()); - } - } - - private void setRecursiveHighlighted(boolean b) { - LineWidget cur = predecessor; - while (cur != null) { - cur.setHighlighted(b); - cur = cur.predecessor; - } - - highlightSuccessors(b); - this.setHighlighted(b); - } - - private void highlightSuccessors(boolean b) { - for (LineWidget s : successors) { - s.setHighlighted(b); - s.highlightSuccessors(b); - } - } - - private void setRecursivePopupVisible(boolean b) { - LineWidget cur = predecessor; - while (cur != null) { - cur.setPopupVisible(b); - cur = cur.predecessor; - } - - popupVisibleSuccessors(b); - setPopupVisible(b); - } - - private void popupVisibleSuccessors(boolean b) { - for (LineWidget s : successors) { - s.setPopupVisible(b); - s.popupVisibleSuccessors(b); - } - } - - @Override - public JPopupMenu getPopupMenu(Widget widget, Point localLocation) { - JPopupMenu menu = new JPopupMenu(); - menu.add(scene.createGotoAction(outputSlot.getFigure())); - menu.addSeparator(); - - for (Connection c : connections) { - InputSlot s = c.getInputSlot(); - menu.add(scene.createGotoAction(s.getFigure())); - } - - final LineWidget w = this; - menu.addPopupMenuListener(new PopupMenuListener() { - - @Override - public void popupMenuWillBecomeVisible(PopupMenuEvent e) { - w.setRecursivePopupVisible(true); - } - - @Override - public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { - w.setRecursivePopupVisible(false); - } - - @Override - public void popupMenuCanceled(PopupMenuEvent e) { - } - }); - - return menu; - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/widgets/OutputSlotWidget.java --- a/visualizer/View/src/com/sun/hotspot/igv/view/widgets/OutputSlotWidget.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.view.widgets; - -import com.sun.hotspot.igv.graph.Figure; -import com.sun.hotspot.igv.graph.OutputSlot; -import com.sun.hotspot.igv.view.scene.DiagramScene; -import java.awt.Point; -import java.util.List; -import org.netbeans.api.visual.widget.Widget; - -/** - * - * @author Thomas Wuerthinger - */ -public class OutputSlotWidget extends SlotWidget { - - private OutputSlot outputSlot; - - public OutputSlotWidget(OutputSlot slot, DiagramScene scene, Widget parent, FigureWidget fw) { - super(slot, scene, parent, fw); - outputSlot = slot; - //init(); - //getFigureWidget().getRightWidget().addChild(this); - Point p = outputSlot.getRelativePosition(); - p.y += getSlot().getFigure().getHeight() - Figure.SLOT_START; - p.x -= this.calculateClientArea().width / 2; - //p.x += this.calculateClientArea().width / 2; - this.setPreferredLocation(p); - } - - public OutputSlot getOutputSlot() { - return outputSlot; - } - - @Override - protected int calculateSlotWidth() { - - List slots = getSlot().getFigure().getOutputSlots(); - assert slots.contains(getSlot()); - return calculateWidth(slots.size()); - - } - /* - protected Point calculateRelativeLocation() { - if (getFigureWidget().getBounds() == null) { - return new Point(0, 0); - } - - double x = this.getFigureWidget().getBounds().width; - List slots = outputSlot.getFigure().getOutputSlots(); - assert slots.contains(outputSlot); - return new Point((int) x, (int) (calculateRelativeY(slots.size(), slots.indexOf(outputSlot)))); - }*/ -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/View/src/com/sun/hotspot/igv/view/widgets/SlotWidget.java --- a/visualizer/View/src/com/sun/hotspot/igv/view/widgets/SlotWidget.java Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,177 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ -package com.sun.hotspot.igv.view.widgets; - -import com.sun.hotspot.igv.graph.Figure; -import com.sun.hotspot.igv.graph.OutputSlot; -import com.sun.hotspot.igv.graph.Slot; -import com.sun.hotspot.igv.util.DoubleClickHandler; -import com.sun.hotspot.igv.view.scene.DiagramScene; -import java.awt.Color; -import java.awt.Font; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.geom.Rectangle2D; -import java.util.HashSet; -import java.util.Set; -import org.netbeans.api.visual.action.WidgetAction; -import org.netbeans.api.visual.model.ObjectState; -import org.netbeans.api.visual.widget.Widget; - -/** - * - * @author Thomas Wuerthinger - */ -public abstract class SlotWidget extends Widget implements DoubleClickHandler { - - private Slot slot; - private FigureWidget figureWidget; - private static double TEXT_ZOOM_FACTOR = 0.9; - private static double ZOOM_FACTOR = 0.6; - private DiagramScene diagramScene; - - public SlotWidget(Slot slot, DiagramScene scene, Widget parent, FigureWidget fw) { - super(scene); - this.diagramScene = scene; - this.slot = slot; - figureWidget = fw; - this.setToolTipText("" + slot.getToolTipText() + ""); - this.setCheckClipping(true); - parent.addChild(this); - - //this.setPreferredBounds(this.calculateClientArea()); - } - - - @Override - protected void notifyStateChanged(ObjectState previousState, ObjectState state) { - super.notifyStateChanged(previousState, state); - repaint(); - } - - public Slot getSlot() { - return slot; - } - - public FigureWidget getFigureWidget() { - return figureWidget; - } - - @Override - protected void paintWidget() { - - if (getScene().getZoomFactor() < ZOOM_FACTOR) { - return; - } - - Graphics2D g = this.getGraphics(); - // g.setColor(Color.DARK_GRAY); - int w = this.getBounds().width; - int h = this.getBounds().height; - - if(getSlot().getSource().getSourceNodes().size() > 0) { - final int SMALLER = 0; - g.setColor(getSlot().getColor()); - - int FONT_OFFSET = 2; - - int s = h - SMALLER; - int rectW = s; - - Font font = this.getSlot().getFigure().getDiagram().getSlotFont(); - if(this.getState().isSelected()) { - font = font.deriveFont(Font.BOLD); - } - - if (getSlot().getShortName() != null && getSlot().getShortName().length() > 0) { - g.setFont(font); - Rectangle2D r1 = g.getFontMetrics().getStringBounds(getSlot().getShortName(), g); - rectW = (int)r1.getWidth() + FONT_OFFSET * 2; - } - g.fillRect(w/2 - rectW/2, 0, rectW-1, s-1); - - if(this.getState().isHighlighted()) { - g.setColor(Color.BLUE); - } else { - g.setColor(Color.BLACK); - } - g.drawRect(w/2 - rectW/2, 0, rectW-1, s-1); - - - if (getSlot().getShortName() != null && getSlot().getShortName().length() > 0 && getScene().getZoomFactor() >= TEXT_ZOOM_FACTOR) { - Rectangle2D r1 = g.getFontMetrics().getStringBounds(getSlot().getShortName(), g); - g.drawString(getSlot().getShortName(), (int) (w - r1.getWidth()) / 2, g.getFontMetrics().getAscent()-1);//(int) (r1.getHeight())); - } - - } else { - - if(this.getState().isHighlighted()) { - g.setColor(Color.BLUE); - } else { - g.setColor(Color.BLACK); - } - int r = 2; - if (slot instanceof OutputSlot) { - g.fillOval(w/2-r, Figure.SLOT_WIDTH - Figure.SLOT_START - r, 2*r, 2*r); - //g.fillArc(w / 2 - r, -r, 2*r, 2*r, 180, 180); - } else { - g.fillOval(w/2-r, Figure.SLOT_START - r, 2*r, 2*r); - //g.fillArc(w / 2 - r, h - r, 2*r, 2*r, 0, 180); - } - } - } - - @Override - protected Rectangle calculateClientArea() { - return new Rectangle(0, 0, slot.getWidth(), Figure.SLOT_WIDTH); - } - - protected abstract int calculateSlotWidth(); - - protected int calculateWidth(int count) { - return getFigureWidget().getFigure().getWidth() / count; - } - - @Override - public void handleDoubleClick(Widget w, WidgetAction.WidgetMouseEvent e) { - Set hiddenNodes = new HashSet<>(diagramScene.getModel().getHiddenNodes()); - if (diagramScene.isAllVisible()) { - hiddenNodes = new HashSet<>(diagramScene.getModel().getGraphToView().getGroup().getAllNodes()); - } - - boolean progress = false; - for(Figure f : diagramScene.getModel().getDiagramToView().getFigures()) { - for(Slot s : f.getSlots()) { - if(DiagramScene.doesIntersect(s.getSource().getSourceNodesAsSet(), slot.getSource().getSourceNodesAsSet())) { - progress = true; - hiddenNodes.removeAll(f.getSource().getSourceNodesAsSet()); - } - } - } - - if(progress) { - this.diagramScene.getModel().showNot(hiddenNodes); - } - } -} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties --- a/visualizer/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -currentVersion=Graal Visualizer {0} -LBL_splash_window_title=Starting Graal Visualizer -SPLASH_WIDTH=475 -SplashProgressBarBounds=0,273,475,6 -SplashProgressBarColor=0xFFFFFF -SplashRunningTextBounds=10,283,460,12 -SplashRunningTextColor=0xFFFFFF diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/branding/core/core.jar/org/netbeans/core/startup/frame.gif Binary file visualizer/branding/core/core.jar/org/netbeans/core/startup/frame.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/branding/core/core.jar/org/netbeans/core/startup/frame32.gif Binary file visualizer/branding/core/core.jar/org/netbeans/core/startup/frame32.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/branding/core/core.jar/org/netbeans/core/startup/frame48.gif Binary file visualizer/branding/core/core.jar/org/netbeans/core/startup/frame48.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/branding/core/core.jar/org/netbeans/core/startup/splash.gif Binary file visualizer/branding/core/core.jar/org/netbeans/core/startup/splash.gif has changed diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties --- a/visualizer/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -CTL_MainWindow_Title=Graal Visualizer {0} -CTL_MainWindow_Title_No_Project=Graal Visualizer {0} diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/build.xml --- a/visualizer/build.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ - - - - - - Builds the module suite Graal Visualizer. - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/nbproject/build-impl.xml --- a/visualizer/nbproject/build-impl.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/nbproject/genfiles.properties --- a/visualizer/nbproject/genfiles.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -build.xml.data.CRC32=3c2c6126 -build.xml.script.CRC32=48934e60 -build.xml.stylesheet.CRC32=eaf9f76a@1.45.1 -# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. -# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=3077accc -nbproject/build-impl.xml.script.CRC32=17b494f7 -nbproject/build-impl.xml.stylesheet.CRC32=0f381476@2.47.1 -nbproject/platform.xml.data.CRC32=3077accc -nbproject/platform.xml.script.CRC32=db9e1f43 -nbproject/platform.xml.stylesheet.CRC32=df8ac4dd@2.47.1 diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/nbproject/platform.properties --- a/visualizer/nbproject/platform.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,212 +0,0 @@ -nbplatform.active=default -bootstrap.url=http://deadlock.netbeans.org/hudson/job/nbms-and-javadoc/lastSuccessfulBuild/artifact/nbbuild/netbeans/harness/tasks.jar -autoupdate.catalog.url=http://updates.netbeans.org/netbeans/updates/7.1.1/uc/final/distribution/catalog.xml.gz -suite.dir=${basedir} -nbplatform.active.dir=${suite.dir}/nbplatform -nbplatform.default.netbeans.dest.dir=${suite.dir}/nbplatform -nbplatform.default.harness.dir=${nbplatform.default.netbeans.dest.dir}/harness -harness.dir=${nbplatform.active.dir}/harness -cluster.path=\ - ${nbplatform.active.dir}/ide:\ - ${nbplatform.active.dir}/platform -disabled.modules=\ - com.jcraft.jsch,\ - com.jcraft.jzlib,\ - org.apache.commons.codec,\ - org.apache.commons.httpclient,\ - org.apache.commons.io,\ - org.apache.commons.lang,\ - org.apache.commons.logging,\ - org.apache.ws.commons.util,\ - org.apache.xml.resolver,\ - org.apache.xmlrpc,\ - org.eclipse.core.contenttype,\ - org.eclipse.core.jobs,\ - org.eclipse.core.net,\ - org.eclipse.core.runtime,\ - org.eclipse.core.runtime.compatibility.auth,\ - org.eclipse.equinox.app,\ - org.eclipse.equinox.common,\ - org.eclipse.equinox.preferences,\ - org.eclipse.equinox.registry,\ - org.eclipse.equinox.security,\ - org.eclipse.jgit,\ - org.eclipse.mylyn.bugzilla.core,\ - org.eclipse.mylyn.commons.core,\ - org.eclipse.mylyn.commons.net,\ - org.eclipse.mylyn.commons.xmlrpc,\ - org.eclipse.mylyn.tasks.core,\ - org.mozilla.rhino.patched,\ - org.netbeans.api.debugger,\ - org.netbeans.api.java.classpath,\ - org.netbeans.api.xml,\ - org.netbeans.core.browser,\ - org.netbeans.core.execution,\ - org.netbeans.core.ide,\ - org.netbeans.core.io.ui,\ - org.netbeans.core.multiview,\ - org.netbeans.core.nativeaccess,\ - org.netbeans.core.osgi,\ - org.netbeans.lib.cvsclient,\ - org.netbeans.lib.terminalemulator,\ - org.netbeans.libs.antlr3.runtime,\ - org.netbeans.libs.bytelist,\ - org.netbeans.libs.commons_net,\ - org.netbeans.libs.freemarker,\ - org.netbeans.libs.git,\ - org.netbeans.libs.ini4j,\ - org.netbeans.libs.jaxb,\ - org.netbeans.libs.jsr223,\ - org.netbeans.libs.junit4,\ - org.netbeans.libs.jvyamlb,\ - org.netbeans.libs.lucene,\ - org.netbeans.libs.smack,\ - org.netbeans.libs.svnClientAdapter,\ - org.netbeans.libs.svnClientAdapter.javahl,\ - org.netbeans.libs.svnClientAdapter.svnkit,\ - org.netbeans.libs.swingx,\ - org.netbeans.libs.xerces,\ - org.netbeans.modules.autoupdate.services,\ - org.netbeans.modules.autoupdate.ui,\ - org.netbeans.modules.bugtracking,\ - org.netbeans.modules.bugtracking.bridge,\ - org.netbeans.modules.bugzilla,\ - org.netbeans.modules.core.kit,\ - org.netbeans.modules.csl.api,\ - org.netbeans.modules.css.editor,\ - org.netbeans.modules.css.lib,\ - org.netbeans.modules.css.visual,\ - org.netbeans.modules.db,\ - org.netbeans.modules.db.core,\ - org.netbeans.modules.db.dataview,\ - org.netbeans.modules.db.drivers,\ - org.netbeans.modules.db.kit,\ - org.netbeans.modules.db.metadata.model,\ - org.netbeans.modules.db.mysql,\ - org.netbeans.modules.db.sql.editor,\ - org.netbeans.modules.db.sql.visualeditor,\ - org.netbeans.modules.dbapi,\ - org.netbeans.modules.defaults,\ - org.netbeans.modules.derby,\ - org.netbeans.modules.dlight.nativeexecution,\ - org.netbeans.modules.dlight.terminal,\ - org.netbeans.modules.editor.bookmarks,\ - org.netbeans.modules.editor.bracesmatching,\ - org.netbeans.modules.editor.codetemplates,\ - org.netbeans.modules.editor.completion,\ - org.netbeans.modules.editor.guards,\ - org.netbeans.modules.editor.indent.project,\ - org.netbeans.modules.editor.kit,\ - org.netbeans.modules.editor.macros,\ - org.netbeans.modules.editor.structure,\ - org.netbeans.modules.extbrowser,\ - org.netbeans.modules.extexecution,\ - org.netbeans.modules.extexecution.destroy,\ - org.netbeans.modules.favorites,\ - org.netbeans.modules.git,\ - org.netbeans.modules.glassfish.common,\ - org.netbeans.modules.gototest,\ - org.netbeans.modules.gsf.codecoverage,\ - org.netbeans.modules.gsf.testrunner,\ - org.netbeans.modules.html,\ - org.netbeans.modules.html.editor,\ - org.netbeans.modules.html.editor.lib,\ - org.netbeans.modules.html.lexer,\ - org.netbeans.modules.html.parser,\ - org.netbeans.modules.html.validation,\ - org.netbeans.modules.httpserver,\ - org.netbeans.modules.hudson,\ - org.netbeans.modules.hudson.git,\ - org.netbeans.modules.hudson.mercurial,\ - org.netbeans.modules.hudson.subversion,\ - org.netbeans.modules.hudson.tasklist,\ - org.netbeans.modules.ide.kit,\ - org.netbeans.modules.image,\ - org.netbeans.modules.javascript.editing,\ - org.netbeans.modules.javascript.hints,\ - org.netbeans.modules.javascript.kit,\ - org.netbeans.modules.javascript.refactoring,\ - org.netbeans.modules.jellytools.ide,\ - org.netbeans.modules.jumpto,\ - org.netbeans.modules.keyring.impl,\ - org.netbeans.modules.languages,\ - org.netbeans.modules.languages.diff,\ - org.netbeans.modules.languages.manifest,\ - org.netbeans.modules.languages.yaml,\ - org.netbeans.modules.lexer.nbbridge,\ - org.netbeans.modules.localhistory,\ - org.netbeans.modules.mercurial,\ - org.netbeans.modules.netbinox,\ - org.netbeans.modules.parsing.api,\ - org.netbeans.modules.parsing.lucene,\ - org.netbeans.modules.print.editor,\ - org.netbeans.modules.project.ant,\ - org.netbeans.modules.project.libraries,\ - org.netbeans.modules.projectui,\ - org.netbeans.modules.projectui.buildmenu,\ - org.netbeans.modules.projectuiapi,\ - org.netbeans.modules.properties,\ - org.netbeans.modules.properties.syntax,\ - org.netbeans.modules.refactoring.api,\ - org.netbeans.modules.schema2beans,\ - org.netbeans.modules.server,\ - org.netbeans.modules.servletapi,\ - org.netbeans.modules.spellchecker,\ - org.netbeans.modules.spellchecker.apimodule,\ - org.netbeans.modules.spellchecker.bindings.htmlxml,\ - org.netbeans.modules.spellchecker.bindings.properties,\ - org.netbeans.modules.spellchecker.dictionary_en,\ - org.netbeans.modules.spellchecker.kit,\ - org.netbeans.modules.spi.actions,\ - org.netbeans.modules.subversion,\ - org.netbeans.modules.swing.validation,\ - org.netbeans.modules.target.iterator,\ - org.netbeans.modules.tasklist.kit,\ - org.netbeans.modules.tasklist.projectint,\ - org.netbeans.modules.tasklist.todo,\ - org.netbeans.modules.tasklist.ui,\ - org.netbeans.modules.terminal,\ - org.netbeans.modules.usersguide,\ - org.netbeans.modules.utilities,\ - org.netbeans.modules.utilities.project,\ - org.netbeans.modules.versioning,\ - org.netbeans.modules.versioning.indexingbridge,\ - org.netbeans.modules.versioning.system.cvss.installer,\ - org.netbeans.modules.versioning.util,\ - org.netbeans.modules.web.client.tools.api,\ - org.netbeans.modules.web.common,\ - org.netbeans.modules.web.indent,\ - org.netbeans.modules.xml,\ - org.netbeans.modules.xml.axi,\ - org.netbeans.modules.xml.catalog,\ - org.netbeans.modules.xml.core,\ - org.netbeans.modules.xml.jaxb.api,\ - org.netbeans.modules.xml.lexer,\ - org.netbeans.modules.xml.multiview,\ - org.netbeans.modules.xml.retriever,\ - org.netbeans.modules.xml.schema.completion,\ - org.netbeans.modules.xml.schema.model,\ - org.netbeans.modules.xml.tax,\ - org.netbeans.modules.xml.text,\ - org.netbeans.modules.xml.tools,\ - org.netbeans.modules.xml.wsdl.model,\ - org.netbeans.modules.xml.xam,\ - org.netbeans.modules.xml.xdm,\ - org.netbeans.modules.xsl,\ - org.netbeans.spi.debugger.ui,\ - org.netbeans.spi.editor.hints,\ - org.netbeans.spi.navigator,\ - org.netbeans.spi.palette,\ - org.netbeans.spi.tasklist,\ - org.netbeans.spi.viewmodel,\ - org.netbeans.swing.dirchooser,\ - org.openide.compat,\ - org.openide.execution,\ - org.openide.options,\ - org.openide.util.enumerations -## Not disabled because of NetBeans bug 206347: -## Applications not using OSGi don't start on NbP 7.1 -# org.netbeans.core.netigso,\ -# org.netbeans.libs.felix,\ -# org.netbeans.libs.osgi,\ - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/nbproject/platform.xml --- a/visualizer/nbproject/platform.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/nbproject/project.properties --- a/visualizer/nbproject/project.properties Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -app.icon=branding/core/core.jar/org/netbeans/core/startup/frame48.gif -app.name=graalvisualizer -app.title=Graal Visualizer -branding.token=${app.name} -modules=\ - ${project.com.sun.hotspot.igv.graph}:\ - ${project.com.sun.hotspot.igv.filter}:\ - ${project.com.sun.hotspot.igv.hierarchicallayout}:\ - ${project.com.sun.hotspot.igv.layout}:\ - ${project.com.sun.hotspot.igv.data}:\ - ${project.com.sun.hotspot.igv.view}:\ - ${project.com.sun.hotspot.igv.bytecodes}:\ - ${project.com.sun.hotspot.igv.difference}:\ - ${project.com.sun.hotspot.igv.settings}:\ - ${project.com.sun.hotspot.igv.util}:\ - ${project.com.sun.hotspot.igv.svg}:\ - ${project.com.sun.hotspot.igv.filterwindow}:\ - ${project.com.sun.hotspot.igv.graal}:\ - ${project.at.ssw.visualizer.cfg}:\ - ${project.org.eclipse.draw2d}:\ - ${project.com.oracle.graal.visualizer.editor}:\ - ${project.com.oracle.graal.visualizer.outline}:\ - ${project.com.oracle.graal.visualizer.snapshots}:\ - ${project.com.oracle.graal.visualizer.sharedactions}:\ - ${project.com.oracle.graal.visualizer.logviewer} -project.at.ssw.visualizer.cfg=ControlFlowEditor -project.com.oracle.graal.visualizer.logviewer=LogViewer -project.com.oracle.graal.visualizer.editor=Editor -project.com.oracle.graal.visualizer.outline=OutlineView -project.com.oracle.graal.visualizer.sharedactions=SharedActions -project.com.oracle.graal.visualizer.snapshots=SnapshotsView -project.com.sun.hotspot.igv.bytecodes=Bytecodes -project.com.sun.hotspot.igv.data=Data -project.com.sun.hotspot.igv.difference=Difference -project.com.sun.hotspot.igv.filter=Filter -project.com.sun.hotspot.igv.filterwindow=FilterWindow -project.com.sun.hotspot.igv.graal=Graal -project.com.sun.hotspot.igv.graph=Graph -project.com.sun.hotspot.igv.hierarchicallayout=HierarchicalLayout -project.com.sun.hotspot.igv.layout=Layout -project.com.sun.hotspot.igv.settings=Settings -project.com.sun.hotspot.igv.svg=BatikSVGProxy -project.com.sun.hotspot.igv.view=View -project.com.sun.hotspot.igv.util=Util - -project.org.eclipse.draw2d=Draw2DLibrary -# Disable assertions for RequestProcessor to prevent annoying messages in case -# of multiple SceneAnimator update tasks in the default RequestProcessor. -run.args.extra = -J-client -J-da:org.openide.util.RequestProcessor -debug.args.extra = -J-client -J-da:org.openide.util.RequestProcessor diff -r 622af5fb8c58 -r 1ceb90be7bac visualizer/nbproject/project.xml --- a/visualizer/nbproject/project.xml Fri Jan 03 16:38:57 2014 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ - - - org.netbeans.modules.apisupport.project.suite - - - Graal Visualizer - - -